#include "protocol_api.h"
#include "protocol_board.h"
#include "protocol_encryption.h"
#include "wifi.h"
/**
 * @brief 获取设备索引
 *
 * @param pIndexOut - 设备索引
 */
static void ProtocolGetDeviceIndex(uint8_t *pIndexOut);

/**
 * @brief 校验验证码数据
 *
 * @param pIndexIn    - 设备索引
 * @param pRandomIn   - 随机数
 * @param pCaptchaOut - 验证码
 */
static void ProtocolCalculatingCaptchaValue(uint8_t *pIndexIn, uint8_t *pRandomIn, uint8_t *pCaptchaOut);

/**
 * @brief 验证报文有效性
 *
 * @param pMessageIn             - 待解析的报文
 * @param ResponseDataLength            - 报文长度
 * @return ProtocolPraseResult_t - 解析结果
 */
static ProtocolPraseResult_t ProtocolVerifyMessageValidity(uint8_t *pMessageIn, uint16_t ResponseDataLength);

/**
 * @brief 解析设置设备功能报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingSettingDeviceFunctionsMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析产品信息报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingProductInformationMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析设置持卡人上限报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingSetNumberOfCardholderMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析获取设备自检结果报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingGetDeviceSelfTestResultsMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析启动设备自检报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingStartDeviceModuleSelfTestMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析心跳报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingHeartbeatMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析设备重启报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingDeviceRebootMessageMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析启动设备恢复出厂设置报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingDeviceFactoryResetMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析设置/查询设备参数报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingSetDeviceParameterMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析设备/查询播报天线报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingDaysRemainingMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析设置/查询卡片识读类型报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingTypeOfCardReadingMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析获取设备属性报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingHardwarePropertiesMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析设置/获取实时时间报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingSetRealTimeMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析设置/获取设备归属报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingEquipmentAttributionMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析启动网络附着报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingStartNetworkAttachmentMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析设备握手报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingDeviceHandshakeMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析查询/清除特定卡类型的顶替时间报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingCardReplaceTimeMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析查询/设置免打扰时间报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingNoDisturbingConfigurationMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析查询/设置门锁分类&分组
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingDoorCategorizationMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析本地注册状态报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingGetLocalRegisterStatusMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析获取已注册密钥数量报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingGetumberOfRegisteredKeysMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析查询特定用户的持卡数据报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingQueryCardholderDataForSpecificUserMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析新增密钥报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingNewKeyMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析删除持卡人报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingDeleteCardholderMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析更新持卡人报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingUpdateCardholderMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析本地注册持卡人报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingLocalRegisterUserMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析上报本地注册结果报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingReportLocalRegisterResultMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析获取持卡人清单报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
// static void ProtocolParsingGetCardholderListMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析获取持卡人文件报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
// static void ProtocolParsingGetCardholderFilePacketMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析批量新增用户报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingBatchNewUsersMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析批量删除用户报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingBatchDeleteUsersMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析上报本地缓存文件属性报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingReportingLocalCacheFilePropertiesMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析上报本地缓存文件报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingReportingLocalCacheFilePacketMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析命令开锁报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingCommandUnlockMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析二维码开锁报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingQrcodeUnlockMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析二维码巡更报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingQrcodePatrolMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析蓝牙虚拟卡报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingBluetoothVirtualCardMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析网络属性报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingNetworkAttachmentMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析下发文件属性报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingOfIssuedDocumentsMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析下发文件数据报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingIssueDocumentMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析实时上报事件报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingRealTimeTriggerEventsMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析获取日志文件堆栈深度报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingObtainTheNumberOfLogFilesMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析获取日志文件报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingGetLogFilePacketMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析上传透传数据报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingPushVendorMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析回复下发第三方设备报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingReceivingVendorMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析外部主机验证密钥结果报文
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingExternalValidationMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

/**
 * @brief 解析测试命令
 *
 * @param pDataIn  - 指向主机推送报文地址的指针变量
 * @param SizeIn   - 推送数据有效长度
 * @param pDataOut - 指向从设备回复数据地址的指针变量
 * @param pSizeOut - 回复数据有效长度
 */
static void ProtocolParsingTestMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut);

const MessageResponse_t ResponseFunction[] = {
    [PLANT_DEVICE_FUNCTION] = ProtocolParsingSettingDeviceFunctionsMessage,
    [PLANT_PRODUCT_MODEL] = ProtocolParsingProductInformationMessage,
    [PLANT_SET_NUMBER_OF_CARDHOLDER] = ProtocolParsingSetNumberOfCardholderMessage,
    [PLANT_GET_DEVICE_MODULE_STATUS] = ProtocolParsingGetDeviceSelfTestResultsMessage,
    [PLANT_START_DEVICE_SELF_TEST] = ProtocolParsingStartDeviceModuleSelfTestMessage,

    [SYSTEM_HEARTBEAT_CMD] = ProtocolParsingHeartbeatMessage,
    [SYSTEM_DEVICE_REBOOT] = ProtocolParsingDeviceRebootMessageMessage,
    [SYSTEM_FACTORY_RESET] = ProtocolParsingDeviceFactoryResetMessage,
    [SYSTEM_DEVICE_PARAM] = ProtocolParsingSetDeviceParameterMessage,
    [SYSTRM_DAYS_REMAINING] = ProtocolParsingDaysRemainingMessage,
    [SYSTEM_READR_CARD_MODE] = ProtocolParsingTypeOfCardReadingMessage,
    [SYSTEM_HARDWARE_PROPERTIES] = ProtocolParsingHardwarePropertiesMessage,
    [SYSTEM_SET_REAL_TIME] = ProtocolParsingSetRealTimeMessage,
    [SYSTEM_OWNERSHIP] = ProtocolParsingEquipmentAttributionMessage,
    [WIRELESS_MODULE_NET_ATTA] = ProtocolParsingStartNetworkAttachmentMessage,
    [SYSTEM_DEVICE_HANDSHAKE] = ProtocolParsingDeviceHandshakeMessage,
    [SYSTEM_CARD_REPLACE_TIME] = ProtocolParsingCardReplaceTimeMessage,
    [SYSTEM_NO_DISTURBING_CONFIG] = ProtocolParsingNoDisturbingConfigurationMessage,
    [SYSTEM_LOCK_CLASSIFICATION] = ProtocolParsingDoorCategorizationMessage,

    [CARDHOLDER_NUMBER_OF_REGISTERED] = ProtocolParsingGetumberOfRegisteredKeysMessage,
    [CARDHOLDER_GET_INFORMATION] = ProtocolParsingQueryCardholderDataForSpecificUserMessage,
    [CARDHOLDER_NEW_CARDHOLDER] = ProtocolParsingNewKeyMessage,
    [CARDHOLDER_DELETE_CARDHOLDER] = ProtocolParsingDeleteCardholderMessage,
    [CARDHOLDER_MODIFY_PERMISSIONS] = ProtocolParsingUpdateCardholderMessage,
    [CARDHOLDER_LOCAL_ENTRY] = ProtocolParsingLocalRegisterUserMessage,
    [CARDHOLDER_REGISTERED_INFORMATION] = ProtocolParsingReportLocalRegisterResultMessage,
    [CARDHOLDER_BATCH_ADDITIONS] = ProtocolParsingBatchNewUsersMessage,
    [CARDHOLDER_BATCH_DETETION] = ProtocolParsingBatchDeleteUsersMessage,
    [CARDHOLDER_GET_LOCAL_REGISTER_STATUS] = ProtocolParsingGetLocalRegisterStatusMessage,

    [REPORT_FILE_ATTRIBUTE] = ProtocolParsingReportingLocalCacheFilePropertiesMessage,
    [UPLOAD_FILE_DATA_PACKET] = ProtocolParsingReportingLocalCacheFilePacketMessage,

    [COMMAND_REMOTE_DOOR_OPENING] = ProtocolParsingCommandUnlockMessage,
    [QROCDE_SCANF_DOOR_OPENING] = ProtocolParsingQrcodeUnlockMessage,
    [QROCDE_SCANF_PATROL] = ProtocolParsingQrcodePatrolMessage,
    [BLUETOOTH_VIRTUAL_CARD] = ProtocolParsingBluetoothVirtualCardMessage,
    [NETWORK_INFORM_ATTRIBUTE] = ProtocolParsingNetworkAttachmentMessage,

    [FILE_NOTIFIES_ATTRIBUTR] = ProtocolParsingOfIssuedDocumentsMessage,
    [FILE_SEND_DATA_PCAKET] = ProtocolParsingIssueDocumentMessage,
    [FILE_REQUEST_EIGENVALUE_ATTRIBUTR] = NULL,
    [FILE_REQUEST_EIGENVALUE_FILE] = NULL,

    [LOG_REAL_TIME_EVENT_REPORTING] = ProtocolParsingRealTimeTriggerEventsMessage,
    [LOG_NUMBER_OF_LOGS_OBTAINED] = ProtocolParsingObtainTheNumberOfLogFilesMessage,
    [LOG_OBTAIN_NUMBER_OF_CACHE] = ProtocolParsingGetLogFilePacketMessage,

    [OTHER_TRANSFER_DATA] = ProtocolParsingPushVendorMessage,
    [OTHER_UPLOAD_MESSAGE] = ProtocolParsingReceivingVendorMessage,
    [OTHER_EXTERL_HOST_VALIDATION] = ProtocolParsingExternalValidationMessage,
    [OTHER_CONNECT_TEST] = ProtocolParsingTestMessage,
};

static void ProtocolGetDeviceIndex(uint8_t *pIndexOut)
{
  if (pIndexOut != NULL)
  {
    uint8_t DeviceIndex[PROTOCOL_INDEX_BIT_LENGTH] = {0};

    DeviceIndex[0] = (uint8_t)((PROTOCOL_DEVICE_INDEX_MASK & 0xFF00) >> 8);
    DeviceIndex[1] = (uint8_t)(PROTOCOL_DEVICE_INDEX_MASK & 0x00FF);
    ProtocolGetDeviceMacAddr(&DeviceIndex[2]);

    memcpy(pIndexOut, DeviceIndex, PROTOCOL_INDEX_BIT_LENGTH);
  }
}

static void ProtocolGetDoorDeviceIndex(uint8_t *pIndexOut)
{
  if (pIndexOut != NULL)
  {
    uint8_t DeviceIndex[PROTOCOL_INDEX_BIT_LENGTH] = {0};

    DeviceIndex[0] = (uint8_t)((PROTOCOL_DEVICE_INDEX_MASK & 0xFF00) >> 8);
    DeviceIndex[1] = (uint8_t)(PROTOCOL_DEVICE_INDEX_MASK & 0x00FF);
    GetLockMac(&DeviceIndex[2]);

    memcpy(pIndexOut, DeviceIndex, PROTOCOL_INDEX_BIT_LENGTH);
  }
}

static void ProtocolCalculatingCaptchaValue(uint8_t *pIndexIn, uint8_t *pRandomIn, uint8_t *pCaptchaOut)
{
  for (uint8_t i = 0; i < PROTOCOL_CAPTCHA_BIT_LENGTH; i++)
  {
    pCaptchaOut[i] = pIndexIn[(PROTOCOL_INDEX_BIT_LENGTH - PROTOCOL_CAPTCHA_BIT_LENGTH) + i] ^ pRandomIn[i];
  }
}

static ProtocolPraseResult_t ProtocolVerifyMessageValidity(uint8_t *pMessageIn, uint16_t ResponseDataLength)
{
  uint16_t TimeError = 0;
  uint32_t NowTimestamp = 0, AgreementTimestamp = 0, Ramdon = 0;
  ProtocolFormat_t *pProtocolFormat = (ProtocolFormat_t *)pMessageIn;
  uint8_t Captcha[PROTOCOL_CAPTCHA_BIT_LENGTH] = {0}, MacAddr[PROTOCOL_INDEX_BIT_LENGTH] = {0};

  if (pMessageIn != NULL)
  {
    if (ResponseDataLength > 0)
    {
      if (pProtocolFormat->SyncwordCode == PROTOCOL_SYNCWORD_CODE)
      {
        uint16_t AttaDataSize = (pProtocolFormat->Length[0] << 8) | pProtocolFormat->Length[1];
        if (AttaDataSize <= PROTOCOL_ATTACHED_DATA_LENGTH)
        {
          uint8_t RxMessageCrcValue = ProtocolSumCrcCheck(&pProtocolFormat->SyncwordCode, PROTOCOL_FIXED_BIT_LENGTH + AttaDataSize);
          if (RxMessageCrcValue == pProtocolFormat->Data[AttaDataSize])
          {
            if (ProtocolGetEncryptionFunctionEnableBit() == true)
            {
              ProtocolDecryption(pMessageIn);
            }

            PRINT("[message]: decryption data: ");
            for (uint16_t i = 0; i < ResponseDataLength; i++)
              PRINT("%02X ", pMessageIn[i]);
            PRINT("\r\n");

            ProtocolGetDeviceIndex(MacAddr);
//            printf("get mac %02x %02x %02x %02x %02x %02x %02x %02x\r\n",MacAddr[0],MacAddr[1],
//            MacAddr[2],MacAddr[3],MacAddr[4],MacAddr[5],MacAddr[6],MacAddr[7]);
            if (memcmp(MacAddr, pProtocolFormat->Index, PROTOCOL_INDEX_BIT_LENGTH) == 0)
            {
              uint8_t i=0;
              ProtocolCalculatingCaptchaValue(MacAddr, pProtocolFormat->Random, Captcha);
              if (memcmp(pProtocolFormat->Captcha, Captcha, PROTOCOL_CAPTCHA_BIT_LENGTH) == 0)
              {
                if (pProtocolFormat->Version == PROTOCOL_VERSION_CONTORL)
                {
                  if (ResponseFunction[pProtocolFormat->Command] != NULL)
                  {
                    printf("999999\r\n");
                    NowTimestamp = ProtocolGetCurrentTimestamp();
                    TimeError = ProtocolGetAllowableTimeError() * 60;

                    AgreementTimestamp = pProtocolFormat->TimeStamp[0] << 24;
                    AgreementTimestamp |= pProtocolFormat->TimeStamp[1] << 16;
                    AgreementTimestamp |= pProtocolFormat->TimeStamp[2] << 8;
                    AgreementTimestamp |= pProtocolFormat->TimeStamp[3];
                    printf("pProtocolFormat.cmd %02x \r\n",pProtocolFormat->Command);
//                    printf("AgreementTimestamp %08x NowTimestamp %08x TimeError %04x pProtocolFormat->Command %02x\r\n",AgreementTimestamp,NowTimestamp,TimeError,pProtocolFormat->Command);
                    if (abs((int)(AgreementTimestamp - NowTimestamp)) <= TimeError)
                    {
                      if (ResponseFunction[pProtocolFormat->Command] != NULL)
                        return MESSAGE_PRASE_SUCCESS;
                    }

                    return CMD_LIFE_CYCLE_FAILURE;
                  }

                  return COMMAND_NOT_SUPPORTED;
                }

                return VERSION_INCONSISTENCY;
              }
            }
          }
        }
      }
    }
  }

  return OPERATION_FAILURE;
}

static void ProtocolParsingSettingDeviceFunctionsMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint8_t PraseResult = OPERATION_FAILURE;
  uint16_t ResponseDataLength = 0;
  DeviceFunctionFormat_t DeviceFunction = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      DeviceFunction.Function = *pDataIn++;
      if (ProtocolSetDeviceFunction(DeviceFunction.Function) == true)
      {
        ProtocolUpdateDeviceParamete();

        PraseResult = MESSAGE_PRASE_SUCCESS;
        DeviceFunction.Function = ProtocolGetDeviceFunction();
      }

      if (PraseResult != MESSAGE_PRASE_SUCCESS)
      {
        ProtocolLoadDeviceParametersFromMemory();
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = DeviceFunction.Function;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingProductInformationMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  ProductformationFormat_t ProductformationFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      ProductformationFormat.DeviceType = *pDataIn++;
      ProductformationFormat.DateOfProduction = *pDataIn++ << 24;
      ProductformationFormat.DateOfProduction |= *pDataIn++ << 16;
      ProductformationFormat.DateOfProduction |= *pDataIn++ << 8;
      ProductformationFormat.DateOfProduction |= *pDataIn++;
      memcpy(ProductformationFormat.BoardVersionNumber, pDataIn, NUMBER_OF_FIRMWARE_VERSION);
      pDataIn += NUMBER_OF_FIRMWARE_VERSION;
      memcpy(ProductformationFormat.QualityControlCode, pDataIn, NUMBER_OF_QC_CODE);
      pDataIn += NUMBER_OF_QC_CODE;

      if (ProtocolSetDeviceType(ProductformationFormat.DeviceType) == true)
      {
        if (ProtocolSetDateOfProduction(ProductformationFormat.DateOfProduction) == true)
        {
          if (ProtocolSetBoardVersionNumber(ProductformationFormat.BoardVersionNumber) == true)
          {
            if (ProtocolSetQualityControlCode(ProductformationFormat.QualityControlCode) == true)
            {
              ProtocolUpdateDeviceParamete();

              PraseResult = MESSAGE_PRASE_SUCCESS;
              ProductformationFormat.DeviceType = ProtocolGetDeviceType();
              ProductformationFormat.DateOfProduction = ProtocolGetDateOfProduction();
              ProtocolGetChipModelNumber(ProductformationFormat.ChipModel);
              ProtocolGetBoardVersionNumber(ProductformationFormat.BoardVersionNumber);
              ProtocolGetQualityControlCode(ProductformationFormat.QualityControlCode);
              ProtocolGetFirmwareVersionNumber(ProductformationFormat.FirmwareVersionNumber);
            }
          }
        }
      }

      if (PraseResult != MESSAGE_PRASE_SUCCESS)
      {
        ProtocolLoadDeviceParametersFromMemory();
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = ProductformationFormat.DeviceType;
    pDataOut[ResponseDataLength++] = (uint8_t)((ProductformationFormat.DateOfProduction & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((ProductformationFormat.DateOfProduction & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((ProductformationFormat.DateOfProduction & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(ProductformationFormat.DateOfProduction & 0x000000FF);
    memcpy(&pDataOut[ResponseDataLength], ProductformationFormat.BoardVersionNumber, NUMBER_OF_FIRMWARE_VERSION);
    ResponseDataLength += NUMBER_OF_FIRMWARE_VERSION;
    memcpy(&pDataOut[ResponseDataLength], ProductformationFormat.QualityControlCode, NUMBER_OF_QC_CODE);
    ResponseDataLength += NUMBER_OF_QC_CODE;
    memcpy(&pDataOut[ResponseDataLength], ProductformationFormat.FirmwareVersionNumber, NUMBER_OF_FIRMWARE_VERSION);
    ResponseDataLength += NUMBER_OF_FIRMWARE_VERSION;
    memcpy(&pDataOut[ResponseDataLength], ProductformationFormat.ChipModel, NUMBER_OF_CHIP_TYPE_LENGTH);
    ResponseDataLength += NUMBER_OF_CHIP_TYPE_LENGTH;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingSetNumberOfCardholderMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  SetNumberOfCardholderFormat_t SetNumberOfCardholderFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      SetNumberOfCardholderFormat.NumberOfCardholders = *pDataIn++;
      if (ProtocolSetNumberOfCardholder(SetNumberOfCardholderFormat.NumberOfCardholders) == true)
      {
        ProtocolUpdateDeviceParamete();

        PraseResult = MESSAGE_PRASE_SUCCESS;
        SetNumberOfCardholderFormat.NumberOfCardholders = ProtocolGetNumberOfCardholder();
      }

      if (PraseResult != MESSAGE_PRASE_SUCCESS)
      {
        ProtocolLoadDeviceParametersFromMemory();
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = SetNumberOfCardholderFormat.NumberOfCardholders;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingGetDeviceSelfTestResultsMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  GetSelfTestStatusFormat_t GetSelfTestStatus = {0};

  if (pDataOut != NULL)
  {
    GetSelfTestStatus.SelfTestResult = ProtocolGetSelfTestResult();
    GetSelfTestStatus.BatteryLevel = ProtocolGetVoltagePercentage();
    GetSelfTestStatus.Moduletatus.ModuleBitStatus.Rfid = ProtocolGetRfidFailureIdent();
    GetSelfTestStatus.Moduletatus.ModuleBitStatus.Camera = ProtocolGetFaceFailureIdent();
    GetSelfTestStatus.Moduletatus.ModuleBitStatus.Finger = ProtocolGetFingerFailureIdent();
    GetSelfTestStatus.Moduletatus.ModuleBitStatus.Keyboard = ProtocolGetKeyboardFailureIdent();
    GetSelfTestStatus.Moduletatus.ModuleBitStatus.WirelessModule = ProtocolGetWirelessFailureIdent();

    pDataOut[ResponseDataLength++] = MESSAGE_PRASE_SUCCESS;
    pDataOut[ResponseDataLength++] = GetSelfTestStatus.SelfTestResult;
    pDataOut[ResponseDataLength++] = (uint8_t)((GetSelfTestStatus.Moduletatus.Status & 0xFF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(GetSelfTestStatus.Moduletatus.Status & 0x00FF);
    pDataOut[ResponseDataLength++] = GetSelfTestStatus.BatteryLevel;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingStartDeviceModuleSelfTestMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;

  PraseResult = (ProtocolStartDeviceSelfTestTask() == true) ? MESSAGE_PRASE_SUCCESS : TARGET_DEVICE_BUSY;

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingHeartbeatMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint8_t ResponseCode = 0;
  HeartbeatFormat_t HeartbeatFormat = {0};

  if (pDataIn != NULL)
  {
    if (SizeIn > 0)
    {
      ResponseCode = *pDataIn++;
      if (ResponseCode == MESSAGE_PRASE_SUCCESS)
      {
        HeartbeatFormat.RealTimeTime = *pDataIn++ << 24;
        HeartbeatFormat.RealTimeTime |= *pDataIn++ << 16;
        HeartbeatFormat.RealTimeTime |= *pDataIn++ << 8;
        HeartbeatFormat.RealTimeTime |= *pDataIn++;
        HeartbeatFormat.TimeZone = *pDataIn++;

        if (HeartbeatFormat.TimeZone != ProtocolGetTimeZone())
        {
          if (ProtocolSetTimeZone(HeartbeatFormat.TimeZone) == true)
          {
            ProtocolUpdateDeviceParamete();
          }
        }

        ProtocolResetAccumulatedTimeOfHeartbeats();
        ProtocolSetCurrentTimestamp(HeartbeatFormat.RealTimeTime);
      }
    }
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = 0;
  }
}

static void ProtocolParsingDeviceRebootMessageMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  printf("rebot \r\n");
  if (pDataOut != NULL)
  {
    //暂时屏蔽，软件更改后可开启
    pDataOut[ResponseDataLength++] = (ProtocolStartDeviceRebootTask() == true) ? MESSAGE_PRASE_SUCCESS : OPERATION_FAILURE;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingDeviceFactoryResetMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;

  PraseResult = (ProtocolStartDeviceFactoryResetTask() == true) ? MESSAGE_PRASE_SUCCESS : PraseResult;

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingSetDeviceParameterMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  ParameterOfApparatusFormat_t ParameterOfApparatusFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      ParameterOfApparatusFormat.SystemVolume = *pDataIn++;
      ParameterOfApparatusFormat.UnlockingTime = *pDataIn++;
      ParameterOfApparatusFormat.HeartbeatInterval = *pDataIn++ << 8;
      ParameterOfApparatusFormat.HeartbeatInterval |= *pDataIn++;
      ParameterOfApparatusFormat.CameraSearchTimeout = *pDataIn++;
      ParameterOfApparatusFormat.CameraReadModel = *pDataIn++;
      ParameterOfApparatusFormat.ErrorsExcepted = *pDataIn++;
      ParameterOfApparatusFormat.Sensitivity = *pDataIn++;
      ParameterOfApparatusFormat.NetworkOperator = *pDataIn++;
      ParameterOfApparatusFormat.BluetoothConnectTime = *pDataIn++;
      ParameterOfApparatusFormat.BreakInDetectionInterval = *pDataIn++;
      ParameterOfApparatusFormat.FlaseLockDetectionInterval = *pDataIn++;
      ParameterOfApparatusFormat.NormalOpenReminderInterval = *pDataIn++;
      ParameterOfApparatusFormat.LockedInReminderInterval = *pDataIn++;
      ParameterOfApparatusFormat.OfflineCardFunctionEn = *pDataIn++;
      ParameterOfApparatusFormat.MotorDriveTime = *pDataIn++;
      ParameterOfApparatusFormat.BluetoothUpdateRadioInterval = *pDataIn++;
      memcpy(ParameterOfApparatusFormat.Reserved, pDataIn, 10);
      pDataIn += 10;

      if (ProtocolSetSystemVolume(ParameterOfApparatusFormat.SystemVolume) == true)
      {
        if (ProtocolSetMotorDriveTime(ParameterOfApparatusFormat.MotorDriveTime) == true)
        {
          if (ProtocolSetUnlockingTime(ParameterOfApparatusFormat.UnlockingTime) == true)
          {
            if (ProtocolSetHeartbeatInterval(ParameterOfApparatusFormat.HeartbeatInterval) == true)
            {
              if (ProtocolSetCameraRecognitionTimeout(ParameterOfApparatusFormat.CameraSearchTimeout) == true)
              {
                if (ProtocolSetCamearReadingMode(ParameterOfApparatusFormat.CameraReadModel) == true)
                {
                  if (ProtocolSetAllowableTimeError(ParameterOfApparatusFormat.ErrorsExcepted) == true)
                  {
                    if (ProtocolSetKeyboardSensitivity(ParameterOfApparatusFormat.Sensitivity) == true)
                    {
                      if (ProtocolSetAcquireNetworkOperators(ParameterOfApparatusFormat.NetworkOperator) == true)
                      {
                        if (ProtocolSetBluetoothConnectionTimeout(ParameterOfApparatusFormat.BluetoothConnectTime) == true)
                        {
                          if (ProtocolSetOfflineCardFunctionEnable(ParameterOfApparatusFormat.OfflineCardFunctionEn) == true)
                          {
                            if (ProtocolSetBreakInDetcetionInterval(ParameterOfApparatusFormat.BreakInDetectionInterval) == true)
                            {
                              if (ProtocolSetLockedInReminderInterval(ParameterOfApparatusFormat.LockedInReminderInterval) == true)
                              {
                                if (ProtocolSetFalseLockDetcetionInterval(ParameterOfApparatusFormat.FlaseLockDetectionInterval) == true)
                                {
                                  if (ProtocolSetNormalOpenReminderInterval(ParameterOfApparatusFormat.NormalOpenReminderInterval) == true)
                                  {
                                    if (ProtocolSetBluetoothUpdateRaidioInterval(ParameterOfApparatusFormat.BluetoothUpdateRadioInterval) == true)
                                    {
                                      ProtocolUpdateDeviceParamete();

                                      PraseResult = MESSAGE_PRASE_SUCCESS;
                                      ParameterOfApparatusFormat.SystemVolume = ProtocolGetSystemVolume();
                                      ParameterOfApparatusFormat.UnlockingTime = ProtocolGetUnlockingTime();
                                      ParameterOfApparatusFormat.MotorDriveTime = ProtocolGetMotorDriveTime();
                                      ParameterOfApparatusFormat.Sensitivity = ProtocolGetKeyboardSensitivity();
                                      ParameterOfApparatusFormat.ErrorsExcepted = ProtocolGetAllowableTimeError();
                                      ParameterOfApparatusFormat.CameraReadModel = ProtocolGetCamearReadingMode();
                                      ParameterOfApparatusFormat.HeartbeatInterval = ProtocolGetHeartbeatInterval();
                                      ParameterOfApparatusFormat.NetworkOperator = ProtocolGetAcquireNetworkOperators();
                                      ParameterOfApparatusFormat.CameraSearchTimeout = ProtocolGetCameraRecognitionTimeout();
                                      ParameterOfApparatusFormat.OfflineCardFunctionEn = ProtocolGetOfflineCardFunctionEnable();
                                      ParameterOfApparatusFormat.BluetoothConnectTime = ProtocolGetBluetoothConnectionTimeout();
                                      ParameterOfApparatusFormat.LockedInReminderInterval = ProtocolGetLockedInReminderInterval();
                                      ParameterOfApparatusFormat.BreakInDetectionInterval = ProtocolGetTheBreakInDetcetionInterval();
                                      ParameterOfApparatusFormat.FlaseLockDetectionInterval = ProtocolGetFalseLockDetcetionInterval();
                                      ParameterOfApparatusFormat.NormalOpenReminderInterval = ProtocolGetNormalOpenReminderInterval();
                                      ParameterOfApparatusFormat.BluetoothUpdateRadioInterval = ProtocolGetBluetoothUpdateRaidioInterval();
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }

      if (PraseResult != MESSAGE_PRASE_SUCCESS)
      {
        ProtocolLoadDeviceParametersFromMemory();
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = ParameterOfApparatusFormat.SystemVolume;
    pDataOut[ResponseDataLength++] = ParameterOfApparatusFormat.UnlockingTime;
    pDataOut[ResponseDataLength++] = (uint8_t)((ParameterOfApparatusFormat.HeartbeatInterval & 0xFF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(ParameterOfApparatusFormat.HeartbeatInterval & 0x00FF);
    pDataOut[ResponseDataLength++] = ParameterOfApparatusFormat.CameraSearchTimeout;
    pDataOut[ResponseDataLength++] = ParameterOfApparatusFormat.CameraReadModel;
    pDataOut[ResponseDataLength++] = ParameterOfApparatusFormat.ErrorsExcepted;
    pDataOut[ResponseDataLength++] = ParameterOfApparatusFormat.Sensitivity;
    pDataOut[ResponseDataLength++] = ParameterOfApparatusFormat.NetworkOperator;
    pDataOut[ResponseDataLength++] = ParameterOfApparatusFormat.BluetoothConnectTime;
    pDataOut[ResponseDataLength++] = ParameterOfApparatusFormat.BreakInDetectionInterval;
    pDataOut[ResponseDataLength++] = ParameterOfApparatusFormat.FlaseLockDetectionInterval;
    pDataOut[ResponseDataLength++] = ParameterOfApparatusFormat.NormalOpenReminderInterval;
    pDataOut[ResponseDataLength++] = ParameterOfApparatusFormat.LockedInReminderInterval;
    pDataOut[ResponseDataLength++] = ParameterOfApparatusFormat.OfflineCardFunctionEn;
    pDataOut[ResponseDataLength++] = ParameterOfApparatusFormat.MotorDriveTime;
    pDataOut[ResponseDataLength++] = ParameterOfApparatusFormat.BluetoothUpdateRadioInterval;
    memcpy(&pDataOut[ResponseDataLength], ParameterOfApparatusFormat.Reserved, 10);
    ResponseDataLength += 10;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingDaysRemainingMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  DaysRemainingFormat_t DaysRemainingFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      DaysRemainingFormat.En = *pDataIn++;
      DaysRemainingFormat.Days = *pDataIn++;

      if (ProtocolSetDayBroadcastContorlEn(DaysRemainingFormat.En) == true)
      {
        if (ProtocolSetBroadcastRemainingDays(DaysRemainingFormat.Days) == true)
        {
          ProtocolUpdateDeviceParamete();

          PraseResult = MESSAGE_PRASE_SUCCESS;
          DaysRemainingFormat.En = ProtocolGetDayBroadcastContorlEn();
          DaysRemainingFormat.Days = ProtocolGetBroadcastRemainingDays();
        }
      }

      if (PraseResult != MESSAGE_PRASE_SUCCESS)
      {
        ProtocolLoadDeviceParametersFromMemory();
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = DaysRemainingFormat.En;
    pDataOut[ResponseDataLength++] = DaysRemainingFormat.Days;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingTypeOfCardReadingMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  TypeOfReadingFormat_t TypeOfReadingFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      TypeOfReadingFormat.CardType = *pDataIn++;

      if (ProtocolSetReadTheCardType(TypeOfReadingFormat.CardType) == true)
      {
        ProtocolUpdateDeviceParamete();

        PraseResult = MESSAGE_PRASE_SUCCESS;
        TypeOfReadingFormat.CardType = ProtocolGetReadTheCardType();
      }

      if (PraseResult != MESSAGE_PRASE_SUCCESS)
      {
        ProtocolLoadDeviceParametersFromMemory();
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = TypeOfReadingFormat.CardType;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingHardwarePropertiesMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  char TmpDataBuff[40] = {0};
  uint16_t ResponseDataLength = 0;

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = MESSAGE_PRASE_SUCCESS;
    pDataOut[ResponseDataLength++] = SUBCOMMAND_DEVICE_TYPE;
    pDataOut[ResponseDataLength++] = 1;
    pDataOut[ResponseDataLength++] = ProtocolGetDeviceType();

    uint32_t DataOfProduction = ProtocolGetDateOfProduction();
    pDataOut[ResponseDataLength++] = SUBCOMMAND_DATA_OF_PRODUCTION;
    pDataOut[ResponseDataLength++] = 4;
    pDataOut[ResponseDataLength++] = (uint8_t)((DataOfProduction & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((DataOfProduction & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((DataOfProduction & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(DataOfProduction & 0x000000FF);

    memset(TmpDataBuff, 0, 40);
    ProtocolGetBoardVersionNumber(TmpDataBuff);
    pDataOut[ResponseDataLength++] = SUBCOMMAND_BOARD_VERSION;
    pDataOut[ResponseDataLength++] = strlen(TmpDataBuff);
    memcpy(&pDataOut[ResponseDataLength], TmpDataBuff, strlen(TmpDataBuff));
    ResponseDataLength += strlen(TmpDataBuff);

    memset(TmpDataBuff, 0, 40);
    ProtocolGetFirmwareVersionNumber(TmpDataBuff);
    pDataOut[ResponseDataLength++] = SUBCOMMAND_FIRMWARE_VERSION;
    pDataOut[ResponseDataLength++] = strlen(TmpDataBuff);
    memcpy(&pDataOut[ResponseDataLength], TmpDataBuff, strlen(TmpDataBuff));
    ResponseDataLength += strlen(TmpDataBuff);

    memset(TmpDataBuff, 0, 40);
    ProtocolGetQualityControlCode(TmpDataBuff);
    pDataOut[ResponseDataLength++] = SUBCOMMAND_QUALITY_INSPECTOR;
    pDataOut[ResponseDataLength++] = strlen(TmpDataBuff);
    memcpy(&pDataOut[ResponseDataLength], TmpDataBuff, strlen(TmpDataBuff));
    ResponseDataLength += strlen(TmpDataBuff);

    memset(TmpDataBuff, 0, 40);
    ProtocolGetChipModelNumber(TmpDataBuff);
    pDataOut[ResponseDataLength++] = SUBCOMMAND_CHIP_MODEL_NUMBER;
    pDataOut[ResponseDataLength++] = strlen(TmpDataBuff);
    memcpy(&pDataOut[ResponseDataLength], TmpDataBuff, strlen(TmpDataBuff));
    ResponseDataLength += strlen(TmpDataBuff);

#if _SAFETY_VERIFYFUNCTION_ENABLE_
#if _SAFETY_MODULE_TYPE_ == _FACE_SAFETY_MODULE_
    memset(TmpDataBuff, 0, 40);
    ProtocolGetSafetyModuleSerialNumber(TmpDataBuff);
    pDataOut[ResponseDataLength++] = SUBCOMMAND_CAMERA_MODULE_SERIAL_NUMBER;
    pDataOut[ResponseDataLength++] = strlen(TmpDataBuff);
    memcpy(&pDataOut[ResponseDataLength], TmpDataBuff, strlen(TmpDataBuff));
    ResponseDataLength += strlen(TmpDataBuff);

    memset(TmpDataBuff, 0, 40);
    ProtocolGetSafetyModuleApplicationVersion(TmpDataBuff);
    pDataOut[ResponseDataLength++] = SUBCOMMAND_CAMERA_MODULE_VERSION;
    pDataOut[ResponseDataLength++] = strlen(TmpDataBuff);
    memcpy(&pDataOut[ResponseDataLength], TmpDataBuff, strlen(TmpDataBuff));
    ResponseDataLength += strlen(TmpDataBuff);

    memset(TmpDataBuff, 0, 40);
    ProtocolGetSafetyModuleAlgorithmVersion(TmpDataBuff);
    pDataOut[ResponseDataLength++] = SUBCOMMAND_FACE_ALGORITHM_VERSION;
    pDataOut[ResponseDataLength++] = strlen(TmpDataBuff);
    memcpy(&pDataOut[ResponseDataLength], TmpDataBuff, strlen(TmpDataBuff));
    ResponseDataLength += strlen(TmpDataBuff);

    pDataOut[ResponseDataLength++] = SUBCOMMAND_NUMBER_OF_REGISTERED_FACE;
    pDataOut[ResponseDataLength++] = 1;
    pDataOut[ResponseDataLength++] = ProtocolGetSafetyModuleNumberOfRegisteredUsers();

#elif _SAFETY_MODULE_TYPE_ == _FINGER_SAFETY_MODULE_
    memset(TmpDataBuff, 0, 40);
    ProtocolGetSafetyModuleSerialNumber(TmpDataBuff);
    pDataOut[ResponseDataLength++] = SUBCOMMAND_FINGER_MODULE_SERIAL_NUMBER;
    pDataOut[ResponseDataLength++] = strlen(TmpDataBuff);
    memcpy(&pDataOut[ResponseDataLength], TmpDataBuff, strlen(TmpDataBuff));
    ResponseDataLength += strlen(TmpDataBuff);

    memset(TmpDataBuff, 0, 40);
    ProtocolGetSafetyModuleApplicationVersion(TmpDataBuff);
    pDataOut[ResponseDataLength++] = SUBCOMMAND_FINGER_MODULE_VERSION;
    pDataOut[ResponseDataLength++] = strlen(TmpDataBuff);
    memcpy(&pDataOut[ResponseDataLength], TmpDataBuff, strlen(TmpDataBuff));
    ResponseDataLength += strlen(TmpDataBuff);

    pDataOut[ResponseDataLength++] = SUBCOMMAND_NUMBER_OF_REGISTERED_FINGER;
    pDataOut[ResponseDataLength++] = 1;
    pDataOut[ResponseDataLength++] = ProtocolGetSafetyModuleNumberOfRegisteredUsers();
#endif
#endif

#if _NETWOK_FUNCTION_ENABLE_
    memset(TmpDataBuff, 0, 40);
    ProtocolGetWirelessModuleSerialNumber(TmpDataBuff);
    pDataOut[ResponseDataLength++] = SUBCOMMAND_WIRELESS_MODULE_SERIAL_NUMBER;
    pDataOut[ResponseDataLength++] = strlen(TmpDataBuff);
    memcpy(&pDataOut[ResponseDataLength], TmpDataBuff, strlen(TmpDataBuff));
    ResponseDataLength += strlen(TmpDataBuff);

    memset(TmpDataBuff, 0, 40);
    ProtocolGetWirelessModuleApplication(TmpDataBuff);
    pDataOut[ResponseDataLength++] = SUBCOMMAND_WIRELESS_MODULE_VERSION;
    pDataOut[ResponseDataLength++] = strlen(TmpDataBuff);
    memcpy(&pDataOut[ResponseDataLength], TmpDataBuff, strlen(TmpDataBuff));
    ResponseDataLength += strlen(TmpDataBuff);

    if (ProtocolGetCat1FunctionEnableBit() == true)
    {
      memset(TmpDataBuff, 0, 40);
      ProtocolGetWirelessSimCardNumber(TmpDataBuff);
      pDataOut[ResponseDataLength++] = SUBCOMMAND_SIM_ICCID;
      pDataOut[ResponseDataLength++] = strlen(TmpDataBuff);
      memcpy(&pDataOut[ResponseDataLength], TmpDataBuff, strlen(TmpDataBuff));
      ResponseDataLength += strlen(TmpDataBuff);

      memset(TmpDataBuff, 0, 40);
      ProtocolGetWirelessImsiCode(TmpDataBuff);
      pDataOut[ResponseDataLength++] = SUBCOMMAND_IMSI_CODE;
      pDataOut[ResponseDataLength++] = strlen(TmpDataBuff);
      memcpy(&pDataOut[ResponseDataLength], TmpDataBuff, strlen(TmpDataBuff));
      ResponseDataLength += strlen(TmpDataBuff);
    }
#endif
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingSetRealTimeMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  RealTimeFormat_t RealTimeFormat = {0};
  uint8_t PraseResult = OPERATION_FAILURE;

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      RealTimeFormat.NowTimestamp = *pDataIn++ << 24;
      RealTimeFormat.NowTimestamp |= *pDataIn++ << 16;
      RealTimeFormat.NowTimestamp |= *pDataIn++ << 8;
      RealTimeFormat.NowTimestamp |= *pDataIn++;
      RealTimeFormat.TimeZoneOffset = *pDataIn++;

      if (ProtocolSetCurrentTimestamp(RealTimeFormat.NowTimestamp) == true)
      {
        if (ProtocolSetTimeZone(RealTimeFormat.TimeZoneOffset) == true)
        {
          ProtocolUpdateDeviceParamete();
          
          PraseResult = MESSAGE_PRASE_SUCCESS;
          RealTimeFormat.TimeZoneOffset = ProtocolGetTimeZone();
          RealTimeFormat.NowTimestamp = ProtocolGetCurrentTimestamp();
        }
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = (uint8_t)((RealTimeFormat.NowTimestamp & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((RealTimeFormat.NowTimestamp & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((RealTimeFormat.NowTimestamp & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(RealTimeFormat.NowTimestamp & 0x000000FF);
    pDataOut[ResponseDataLength++] = RealTimeFormat.TimeZoneOffset;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingEquipmentAttributionMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  EquipmentOwnershipFormat_t EquipmentOwnershipFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      EquipmentOwnershipFormat.ParkNumber = *pDataIn++;
      EquipmentOwnershipFormat.BuildingNumber = *pDataIn++;
      EquipmentOwnershipFormat.FloorNumber = *pDataIn++;
      EquipmentOwnershipFormat.RoomNumber = *pDataIn++ << 24;
      EquipmentOwnershipFormat.RoomNumber |= *pDataIn++ << 16;
      EquipmentOwnershipFormat.RoomNumber |= *pDataIn++ << 8;
      EquipmentOwnershipFormat.RoomNumber |= *pDataIn++;
      EquipmentOwnershipFormat.ChildRommNumber = *pDataIn++;

      if (ProtocolSetParkNumber(EquipmentOwnershipFormat.ParkNumber) == true)
      {
        if (ProtocolSetBuildingNumber(EquipmentOwnershipFormat.BuildingNumber) == true)
        {
          if (ProtocolSetFloorNumber(EquipmentOwnershipFormat.FloorNumber) == true)
          {
            if (ProtocolSetRoomNumber(EquipmentOwnershipFormat.RoomNumber) == true)
            {
              if (ProtocolSetChildRommNumber(EquipmentOwnershipFormat.ChildRommNumber) == true)
              {
                ProtocolUpdateDeviceParamete();

                PraseResult = MESSAGE_PRASE_SUCCESS;
                EquipmentOwnershipFormat.ParkNumber = ProtocolGetParkNumber();
                EquipmentOwnershipFormat.BuildingNumber = ProtocolGetBuildingNumber();
                EquipmentOwnershipFormat.FloorNumber = ProtocolGetFloorNumber();
                EquipmentOwnershipFormat.RoomNumber = ProtocolGetRoomNumber();
                EquipmentOwnershipFormat.ChildRommNumber = ProtocolGetChildRommNumber();
              }
            }
          }
        }
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = EquipmentOwnershipFormat.ParkNumber;
    pDataOut[ResponseDataLength++] = EquipmentOwnershipFormat.BuildingNumber;
    pDataOut[ResponseDataLength++] = EquipmentOwnershipFormat.FloorNumber;
    pDataOut[ResponseDataLength++] = (uint8_t)((EquipmentOwnershipFormat.RoomNumber & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((EquipmentOwnershipFormat.RoomNumber & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((EquipmentOwnershipFormat.RoomNumber & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(EquipmentOwnershipFormat.RoomNumber & 0x000000FF);
    pDataOut[ResponseDataLength++] = EquipmentOwnershipFormat.ChildRommNumber;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingStartNetworkAttachmentMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  WirelessModuleNetAttaFormat_t WirelessModuleNetAttaFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      WirelessModuleNetAttaFormat.OperationType = *pDataIn++;

#if ((_NETWOK_FUNCTION_ENABLE_) && (_NETWOK_MODLE_TYPE_ == _TP1107_MODULE_))
      PraseResult = MESSAGE_PRASE_SUCCESS;
      WirelessModuleNetAttaFormat.NetworkAttachmentStatus = ProtocolGetNetworkAttachmentStatus();

      if (WirelessModuleNetAttaFormat.OperationType == START_WIRELESS_MODULE_NET_ATTA)
      {
        if (ProtocolStartNetworkAttachmentTask() != true)
        {
          PraseResult = TARGET_DEVICE_BUSY;
        }
      }
#else
      PraseResult = COMMAND_NOT_SUPPORTED;
#endif
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = WirelessModuleNetAttaFormat.OperationType;
    pDataOut[ResponseDataLength++] = WirelessModuleNetAttaFormat.NetworkAttachmentStatus;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingDeviceHandshakeMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  DeviceHandshakeFormat_t DeviceHandshakeFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      PraseResult = MESSAGE_PRASE_SUCCESS;

      DeviceHandshakeFormat.Count = *pDataIn++;
      DeviceHandshakeFormat.UseEndTime = *pDataIn++ << 24;
      DeviceHandshakeFormat.UseEndTime |= *pDataIn++ << 16;
      DeviceHandshakeFormat.UseEndTime |= *pDataIn++ << 8;
      DeviceHandshakeFormat.UseEndTime |= *pDataIn++;
      memcpy(DeviceHandshakeFormat.EncryptionKey, pDataIn, ENCRYPTION_KEY_LENGTH);
      pDataIn += ENCRYPTION_KEY_LENGTH;
      memcpy(DeviceHandshakeFormat.AdminPassword, pDataIn, NUMBER_OF_KEYBOARD_KEY);
      pDataIn += NUMBER_OF_KEYBOARD_KEY;
      memcpy(DeviceHandshakeFormat.CardAccessKey, pDataIn, CRAD_SECTOR_KEY_LENGTH);
      pDataIn += CRAD_SECTOR_KEY_LENGTH;
      DeviceHandshakeFormat.CardStartSector = *pDataIn++;
      DeviceHandshakeFormat.CustomerCode = *pDataIn++ << 24;
      DeviceHandshakeFormat.CustomerCode |= *pDataIn++ << 16;
      DeviceHandshakeFormat.CustomerCode |= *pDataIn++ << 8;
      DeviceHandshakeFormat.CustomerCode |= *pDataIn++;

      if (DeviceHandshakeFormat.Count)
      {
        PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

        if (ProtocolSetCustomerCode(DeviceHandshakeFormat.CustomerCode) == true)
        {
          if (ProtocolSetAuthorizationEndTime(DeviceHandshakeFormat.UseEndTime) == true)
          {
            if (ProtocolSetEncryptionKey(DeviceHandshakeFormat.EncryptionKey) == true)
            {
              if (ProtocolSetSuperAdministratorPassword(DeviceHandshakeFormat.AdminPassword) == true)
              {
                if (ProtocolSetCardOperationSectorKey(DeviceHandshakeFormat.CardAccessKey) == true)
                {
                  if (ProtocolSetCardOperationSector(DeviceHandshakeFormat.CardStartSector) == true)
                  {
                    ProtocolIntoNormalMode();
                    ProtocolUpdateDeviceParamete();
                    // ProtocolStartDeviceRebootTask();  //暂时屏蔽
                     printf("ProtocolParsingDeviceHandshakeMessage\r\n");
                    ProtocolPromptForDeviceActivation();

                    PraseResult = MESSAGE_PRASE_SUCCESS;
                    DeviceHandshakeFormat.CustomerCode = ProtocolGetCustomerCode();
                    DeviceHandshakeFormat.UseEndTime = ProtocolGetAuthorizationEndTime();
                  }
                }
              }
            }
          }
        }

        if (PraseResult != MESSAGE_PRASE_SUCCESS)
        {
          ProtocolLoadDeviceParametersFromMemory();
        }
      }
    }
  }

  if (pDataOut != NULL)
  {
    ProtocolGetDeviceIndex(DeviceHandshakeFormat.MacAddr);

    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = DeviceHandshakeFormat.Count;
    pDataOut[ResponseDataLength++] = (uint8_t)((DeviceHandshakeFormat.UseEndTime & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((DeviceHandshakeFormat.UseEndTime & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((DeviceHandshakeFormat.UseEndTime & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(DeviceHandshakeFormat.UseEndTime & 0x000000FF);
    pDataOut[ResponseDataLength++] = (uint8_t)((DeviceHandshakeFormat.CustomerCode & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((DeviceHandshakeFormat.CustomerCode & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((DeviceHandshakeFormat.CustomerCode & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(DeviceHandshakeFormat.CustomerCode & 0x000000FF);
    memcpy(&pDataOut[ResponseDataLength], DeviceHandshakeFormat.MacAddr, PROTOCOL_INDEX_BIT_LENGTH);
    ResponseDataLength += PROTOCOL_INDEX_BIT_LENGTH;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingCardReplaceTimeMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  CardReplaceFormat_t CardReplaceFormat = {0};

  if (pDataIn != NULL)
  {
    CardReplaceFormat.Ident = *pDataIn++;
    CardReplaceFormat.CardType = *pDataIn++;
    CardReplaceFormat.ReplaceTime = *pDataIn++ << 24;
    CardReplaceFormat.ReplaceTime |= *pDataIn++ << 16;
    CardReplaceFormat.ReplaceTime |= *pDataIn++ << 8;
    CardReplaceFormat.ReplaceTime |= *pDataIn++;
    CardReplaceFormat.ReplaceId = *pDataIn++ << 8;
    CardReplaceFormat.ReplaceId |= *pDataIn++;
  }

  if (pDataOut != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if ((CardReplaceFormat.Ident == CARD_REPLACE_GET) || (CardReplaceFormat.Ident == CARD_REPLACE_SET))
    {
      bool ActiveType = (CardReplaceFormat.Ident == CARD_REPLACE_SET) ? true : false;
      if (ProtocolRWCardReplaceTime(CardReplaceFormat.CardType, &CardReplaceFormat.ReplaceTime, &CardReplaceFormat.ReplaceId, ActiveType) == true)
      {
        PraseResult = MESSAGE_PRASE_SUCCESS;
      }
    }

    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = CardReplaceFormat.Ident;
    pDataOut[ResponseDataLength++] = CardReplaceFormat.CardType;
    pDataOut[ResponseDataLength++] = (uint8_t)((CardReplaceFormat.ReplaceTime & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((CardReplaceFormat.ReplaceTime & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((CardReplaceFormat.ReplaceTime & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(CardReplaceFormat.ReplaceTime & 0x000000FF);
    pDataOut[ResponseDataLength++] = (uint8_t)((CardReplaceFormat.ReplaceId & 0xFF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(CardReplaceFormat.ReplaceId & 0x00FF);
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingNoDisturbingConfigurationMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  NoDisturbingFormat_t NoDisturbingFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      NoDisturbingFormat.StartHour = *pDataIn++;
      NoDisturbingFormat.StartMinute = *pDataIn++;
      NoDisturbingFormat.EndHour = *pDataIn++;
      NoDisturbingFormat.EndMinute = *pDataIn++;

      if (ProtocolSetNoDisturbingStartHour(NoDisturbingFormat.StartHour) == true)
      {
        if (ProtocolSetNoDisturbingStartMinute(NoDisturbingFormat.StartMinute) == true)
        {
          if (ProtocolSetNoDisturbingEndtHour(NoDisturbingFormat.EndHour) == true)
          {
            if (ProtocolSetNoDisturbingEndMinute(NoDisturbingFormat.EndMinute) == true)
            {
              ProtocolUpdateDeviceParamete();

              PraseResult = MESSAGE_PRASE_SUCCESS;
              NoDisturbingFormat.StartHour = ProtocolGetNoDisturbingStartHour();
              NoDisturbingFormat.StartMinute = ProtocolGetNoDisturbingStartMinute();
              NoDisturbingFormat.EndHour = ProtocolGetNoDisturbingEndHour();
              NoDisturbingFormat.EndMinute = ProtocolGetNoDisturbingEndMinute();
            }
          }
        }
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = NoDisturbingFormat.StartHour;
    pDataOut[ResponseDataLength++] = NoDisturbingFormat.StartMinute;
    pDataOut[ResponseDataLength++] = NoDisturbingFormat.EndHour;
    pDataOut[ResponseDataLength++] = NoDisturbingFormat.EndMinute;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingDoorCategorizationMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  LockClassificationFormat_t LockClassificationFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      LockClassificationFormat.OperationType = *pDataIn++;

      if ((LockClassificationFormat.OperationType == LOCK_CLASSIFICATION_SET) || (LockClassificationFormat.OperationType == LOCK_CLASSIFICATION_GET))
      {
        if (LockClassificationFormat.OperationType == LOCK_CLASSIFICATION_SET)
        {
          LockClassificationFormat.Lusters = *pDataIn++ << 8;
          LockClassificationFormat.Lusters |= *pDataIn++;

          LockClassificationFormat.Group = *pDataIn++ << 24;
          LockClassificationFormat.Group |= *pDataIn++ << 16;
          LockClassificationFormat.Group |= *pDataIn++ << 8;
          LockClassificationFormat.Group |= *pDataIn++;

          if (ProtocolSetRoomType(LockClassificationFormat.Lusters) == true)
          {
            if (ProtocolSetGroupingNumber(LockClassificationFormat.Group) == true)
            {
              ProtocolUpdateDeviceParamete();

              PraseResult = MESSAGE_PRASE_SUCCESS;
            }
          }
        }
        else
        {
          PraseResult = MESSAGE_PRASE_SUCCESS;
        }

        if (PraseResult == MESSAGE_PRASE_SUCCESS)
        {
          LockClassificationFormat.Lusters = ProtocolGetRoomType();
          LockClassificationFormat.Group = ProtocolGetGroupingNumber();
        }
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = LockClassificationFormat.OperationType;
    pDataOut[ResponseDataLength++] = (uint8_t)((LockClassificationFormat.Lusters & 0xFF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(LockClassificationFormat.Lusters & 0x00FF);
    pDataOut[ResponseDataLength++] = (uint8_t)((LockClassificationFormat.Group & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((LockClassificationFormat.Group & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((LockClassificationFormat.Group & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(LockClassificationFormat.Group & 0x000000FF);
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingGetLocalRegisterStatusMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  LocalRegisterStatusFormat_t LocalRegisterStatusFormat = {0};

  if (pDataOut != NULL)
  {
    LocalRegisterStatusFormat.Step = ProtocolGetLocalRegisterStep();
    LocalRegisterStatusFormat.Result = ProtocolGetLocalRegisterResult();

    pDataOut[ResponseDataLength++] = MESSAGE_PRASE_SUCCESS;
    pDataOut[ResponseDataLength++] = LocalRegisterStatusFormat.Result;
    pDataOut[ResponseDataLength++] = LocalRegisterStatusFormat.Step;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingGetumberOfRegisteredKeysMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  GetNumberOfRegisteredKeysFormat_t GetNumberOfRegisteredKeysFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      PraseResult = COMMAND_NOT_SUPPORTED;

      memcpy(GetNumberOfRegisteredKeysFormat.UserName, pDataIn, USER_NAME_LENGTH);
      pDataIn += USER_NAME_LENGTH;

      if (ProtocolGetExternalValidationFunctionEnableBit() != true)
      {
        PraseResult = MESSAGE_PRASE_SUCCESS;

        GetNumberOfRegisteredKeysFormat.NumberOfRegisterKey = ProtocolGetNumberOfRegisterKeys(GetNumberOfRegisteredKeysFormat.UserName);
        GetNumberOfRegisteredKeysFormat.NumberOfRegisterCardholder = ProtocolGetRegisteredCardholderList(GetNumberOfRegisteredKeysFormat.CardHolderList);
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    memcpy(&pDataOut[ResponseDataLength], GetNumberOfRegisteredKeysFormat.UserName, USER_NAME_LENGTH);
    ResponseDataLength += USER_NAME_LENGTH;
    pDataOut[ResponseDataLength++] = GetNumberOfRegisteredKeysFormat.NumberOfRegisterCardholder;
    pDataOut[ResponseDataLength++] = (uint8_t)((GetNumberOfRegisteredKeysFormat.NumberOfRegisterKey & 0xFF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(GetNumberOfRegisteredKeysFormat.NumberOfRegisterKey & 0x00FF);
    memcpy(&pDataOut[ResponseDataLength], GetNumberOfRegisteredKeysFormat.CardHolderList, GetNumberOfRegisteredKeysFormat.NumberOfRegisterCardholder);
    ResponseDataLength += GetNumberOfRegisteredKeysFormat.NumberOfRegisterCardholder;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingQueryCardholderDataForSpecificUserMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  QueryCardholderInformationFormat_t CardholderInformation = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {

      CardholderInformation.CardholderId = *pDataIn++;
      CardholderInformation.StartNumber = *pDataIn++;
      CardholderInformation.EndNumber = *pDataIn++;
      memcpy(CardholderInformation.UserName, pDataIn, USER_NAME_LENGTH);
      pDataIn += USER_NAME_LENGTH;

      if (CardholderInformation.EndNumber > CardholderInformation.StartNumber)
      {
        PraseResult = COMMAND_NOT_SUPPORTED;

        if (ProtocolGetExternalValidationFunctionEnableBit() != true)
        {
          PraseResult = ProtocolGetUserKeyInformation(CardholderInformation.CardholderId, CardholderInformation.UserName, CardholderInformation.StartNumber,
                                                      CardholderInformation.EndNumber, CardholderInformation.Profile, &CardholderInformation.SizeOfProfile);
        }
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = CardholderInformation.CardholderId;
    pDataOut[ResponseDataLength++] = CardholderInformation.StartNumber;
    pDataOut[ResponseDataLength++] = CardholderInformation.EndNumber;
    memcpy(&pDataOut[ResponseDataLength], CardholderInformation.Profile, CardholderInformation.SizeOfProfile);
    ResponseDataLength += CardholderInformation.SizeOfProfile;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingNewKeyMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  NewCardholderFormat_t NewKeyValueFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      PraseResult = DEVICE_NOT_AUTHORISED;

      memcpy(NewKeyValueFormat.UserName, pDataIn, USER_NAME_LENGTH);
      pDataIn += USER_NAME_LENGTH;
      NewKeyValueFormat.KeyType = *pDataIn++;
      NewKeyValueFormat.KeyToken = *pDataIn++ << 24;
      NewKeyValueFormat.KeyToken |= *pDataIn++ << 16;
      NewKeyValueFormat.KeyToken |= *pDataIn++ << 8;
      NewKeyValueFormat.KeyToken |= *pDataIn++;
      memcpy(NewKeyValueFormat.KeyValue, pDataIn, USER_AUTHENTICATION_KEY_LENGTH);
      pDataIn += USER_AUTHENTICATION_KEY_LENGTH;
      NewKeyValueFormat.Count = *pDataIn++;
      NewKeyValueFormat.Date = *pDataIn++;
      NewKeyValueFormat.StartTimestamp = *pDataIn++ << 24;
      NewKeyValueFormat.StartTimestamp |= *pDataIn++ << 16;
      NewKeyValueFormat.StartTimestamp |= *pDataIn++ << 8;
      NewKeyValueFormat.StartTimestamp |= *pDataIn++;
      NewKeyValueFormat.EndTimestamp = *pDataIn++ << 24;
      NewKeyValueFormat.EndTimestamp |= *pDataIn++ << 16;
      NewKeyValueFormat.EndTimestamp |= *pDataIn++ << 8;
      NewKeyValueFormat.EndTimestamp |= *pDataIn++;

      for (uint8_t i = 0; i < MAX_TIME_SLOTS; i++)
      {
        NewKeyValueFormat.TimePeriod[i].StartHour = *pDataIn++;
        NewKeyValueFormat.TimePeriod[i].StartMinute = *pDataIn++;
        NewKeyValueFormat.TimePeriod[i].EndHour = *pDataIn++;
        NewKeyValueFormat.TimePeriod[i].EndMinute = *pDataIn++;
      }

      if (ProtocolGetDeviceActivationStatus() == true)
      {
        PraseResult = COMMAND_NOT_SUPPORTED;

        if (ProtocolGetExternalValidationFunctionEnableBit() != true)
        {
          PraseResult = ProtocolNewCardholder(&NewKeyValueFormat);
        }
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    memcpy(&pDataOut[ResponseDataLength], NewKeyValueFormat.UserName, USER_NAME_LENGTH);
    ResponseDataLength += USER_NAME_LENGTH;
    pDataOut[ResponseDataLength++] = NewKeyValueFormat.KeyType;
    pDataOut[ResponseDataLength++] = (uint8_t)((NewKeyValueFormat.KeyToken & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((NewKeyValueFormat.KeyToken & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((NewKeyValueFormat.KeyToken & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(NewKeyValueFormat.KeyToken & 0x000000FF);
    memcpy(&pDataOut[ResponseDataLength], NewKeyValueFormat.KeyValue, USER_AUTHENTICATION_KEY_LENGTH);
    ResponseDataLength += USER_AUTHENTICATION_KEY_LENGTH;
    pDataOut[ResponseDataLength++] = NewKeyValueFormat.Count;
    pDataOut[ResponseDataLength++] = NewKeyValueFormat.Date;
    pDataOut[ResponseDataLength++] = (uint8_t)((NewKeyValueFormat.StartTimestamp & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((NewKeyValueFormat.StartTimestamp & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((NewKeyValueFormat.StartTimestamp & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(NewKeyValueFormat.StartTimestamp & 0x000000FF);
    pDataOut[ResponseDataLength++] = (uint8_t)((NewKeyValueFormat.EndTimestamp & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((NewKeyValueFormat.EndTimestamp & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((NewKeyValueFormat.EndTimestamp & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(NewKeyValueFormat.EndTimestamp & 0x000000FF);
    for (uint8_t i = 0; i < MAX_TIME_SLOTS; i++)
    {
      pDataOut[ResponseDataLength++] = NewKeyValueFormat.TimePeriod[i].StartHour;
      pDataOut[ResponseDataLength++] = NewKeyValueFormat.TimePeriod[i].StartMinute;
      pDataOut[ResponseDataLength++] = NewKeyValueFormat.TimePeriod[i].EndHour;
      pDataOut[ResponseDataLength++] = NewKeyValueFormat.TimePeriod[i].EndMinute;
    }
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }

  (PraseResult == MESSAGE_PRASE_SUCCESS) ? ProtocolRemindersKeyOperationSuccess() : ProtocolRemindersKeyOperationError();
}

static void ProtocolParsingDeleteCardholderMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  uint8_t AdminPassword[NUMBER_OF_KEYBOARD_KEY] = {0};
  DeleteCardholderFormat_t DeleteCardholderFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      PraseResult = PERMISSION_DENIED;

      memcpy(DeleteCardholderFormat.UserName, pDataIn, USER_NAME_LENGTH);
      pDataIn += USER_NAME_LENGTH;
      DeleteCardholderFormat.KeyType = *pDataIn++;
      memcpy(DeleteCardholderFormat.KeyValue, pDataIn, USER_AUTHENTICATION_KEY_LENGTH);
      pDataIn += USER_AUTHENTICATION_KEY_LENGTH;
      memcpy(DeleteCardholderFormat.AdministratorPassword, pDataIn, NUMBER_OF_KEYBOARD_KEY);
      pDataIn += NUMBER_OF_KEYBOARD_KEY;

      ProtocolGetSuperAdministratorPassword(AdminPassword);
      if (memcmp(DeleteCardholderFormat.AdministratorPassword, AdminPassword, NUMBER_OF_KEYBOARD_KEY) == 0)
      {
        PraseResult = DEVICE_NOT_AUTHORISED;

        if (ProtocolGetDeviceActivationStatus() == true)
        {
          PraseResult = COMMAND_NOT_SUPPORTED;

          if (ProtocolGetExternalValidationFunctionEnableBit() != true)
          {
            PraseResult = ProtocolDeleteCardholder(&DeleteCardholderFormat);
          }
        }
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    memcpy(&pDataOut[ResponseDataLength], DeleteCardholderFormat.UserName, USER_NAME_LENGTH);
    ResponseDataLength += USER_NAME_LENGTH;
    pDataOut[ResponseDataLength++] = DeleteCardholderFormat.KeyType;
    memcpy(&pDataOut[ResponseDataLength], DeleteCardholderFormat.KeyValue, USER_AUTHENTICATION_KEY_LENGTH);
    ResponseDataLength += USER_AUTHENTICATION_KEY_LENGTH;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }

  (PraseResult == MESSAGE_PRASE_SUCCESS) ? ProtocolRemindersKeyOperationSuccess() : ProtocolRemindersKeyOperationError();
}

static void ProtocolParsingUpdateCardholderMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  uint8_t AdminPassword[NUMBER_OF_KEYBOARD_KEY] = {0};
  UpdateCardholderFormat_t UpdateCardholderFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      PraseResult = PERMISSION_DENIED;

      memcpy(UpdateCardholderFormat.UserName, pDataIn, USER_NAME_LENGTH);
      pDataIn += USER_NAME_LENGTH;
      UpdateCardholderFormat.KeyType = *pDataIn++;
      UpdateCardholderFormat.UserStatus = *pDataIn++;
      memcpy(UpdateCardholderFormat.KeyValue, pDataIn, USER_AUTHENTICATION_KEY_LENGTH);
      pDataIn += USER_AUTHENTICATION_KEY_LENGTH;
      UpdateCardholderFormat.Count = *pDataIn++;
      UpdateCardholderFormat.Date = *pDataIn++;
      UpdateCardholderFormat.StartTimestamp = *pDataIn++ << 24;
      UpdateCardholderFormat.StartTimestamp |= *pDataIn++ << 16;
      UpdateCardholderFormat.StartTimestamp |= *pDataIn++ << 8;
      UpdateCardholderFormat.StartTimestamp |= *pDataIn++;
      UpdateCardholderFormat.EndTimestamp = *pDataIn++ << 24;
      UpdateCardholderFormat.EndTimestamp |= *pDataIn++ << 16;
      UpdateCardholderFormat.EndTimestamp |= *pDataIn++ << 8;
      UpdateCardholderFormat.EndTimestamp |= *pDataIn++;
      for (uint8_t i = 0; i < MAX_TIME_SLOTS; i++)
      {
        UpdateCardholderFormat.TimePeriod[i].StartHour = *pDataIn++;
        UpdateCardholderFormat.TimePeriod[i].StartMinute = *pDataIn++;
        UpdateCardholderFormat.TimePeriod[i].EndHour = *pDataIn++;
        UpdateCardholderFormat.TimePeriod[i].EndMinute = *pDataIn++;
      }
      memcpy(UpdateCardholderFormat.AdministratorPassword, pDataIn, NUMBER_OF_KEYBOARD_KEY);
      pDataIn += NUMBER_OF_KEYBOARD_KEY;

      ProtocolGetSuperAdministratorPassword(AdminPassword);
      if (memcmp(UpdateCardholderFormat.AdministratorPassword, AdminPassword, NUMBER_OF_KEYBOARD_KEY) == 0)
      {
        PraseResult = DEVICE_NOT_AUTHORISED;

        if (ProtocolGetDeviceActivationStatus() == true)
        {
          PraseResult = COMMAND_NOT_SUPPORTED;

          if (ProtocolGetExternalValidationFunctionEnableBit() != true)
          {
            PraseResult = ProtocolUpdateCardholder(&UpdateCardholderFormat);
          }
        }
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    memcpy(&pDataOut[ResponseDataLength], UpdateCardholderFormat.UserName, USER_NAME_LENGTH);
    ResponseDataLength += USER_NAME_LENGTH;
    pDataOut[ResponseDataLength++] = UpdateCardholderFormat.KeyType;
    pDataOut[ResponseDataLength++] = UpdateCardholderFormat.UserStatus;
    memcpy(&pDataOut[ResponseDataLength], UpdateCardholderFormat.KeyValue, USER_AUTHENTICATION_KEY_LENGTH);
    ResponseDataLength += USER_AUTHENTICATION_KEY_LENGTH;
    pDataOut[ResponseDataLength++] = UpdateCardholderFormat.Count;
    pDataOut[ResponseDataLength++] = UpdateCardholderFormat.Date;
    pDataOut[ResponseDataLength++] = (uint8_t)((UpdateCardholderFormat.StartTimestamp & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((UpdateCardholderFormat.StartTimestamp & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((UpdateCardholderFormat.StartTimestamp & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(UpdateCardholderFormat.StartTimestamp & 0x000000FF);
    pDataOut[ResponseDataLength++] = (uint8_t)((UpdateCardholderFormat.EndTimestamp & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((UpdateCardholderFormat.EndTimestamp & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((UpdateCardholderFormat.EndTimestamp & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(UpdateCardholderFormat.EndTimestamp & 0x000000FF);
    for (uint8_t i = 0; i < MAX_TIME_SLOTS; i++)
    {
      pDataOut[ResponseDataLength++] = UpdateCardholderFormat.TimePeriod[i].StartHour;
      pDataOut[ResponseDataLength++] = UpdateCardholderFormat.TimePeriod[i].StartMinute;
      pDataOut[ResponseDataLength++] = UpdateCardholderFormat.TimePeriod[i].EndHour;
      pDataOut[ResponseDataLength++] = UpdateCardholderFormat.TimePeriod[i].EndMinute;
    }
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }

  (PraseResult == MESSAGE_PRASE_SUCCESS) ? ProtocolRemindersKeyOperationSuccess() : ProtocolRemindersKeyOperationError();
}

static void ProtocolParsingLocalRegisterUserMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  uint8_t AdminPassword[NUMBER_OF_KEYBOARD_KEY] = {0};
  LocalRegistrationFormat_t LocalRegistrationFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      PraseResult = PERMISSION_DENIED;

      memcpy(LocalRegistrationFormat.UserName, pDataIn, USER_NAME_LENGTH);
      pDataIn += USER_NAME_LENGTH;
      LocalRegistrationFormat.KeyType = *pDataIn++;
      LocalRegistrationFormat.KeyToken = *pDataIn++ << 24;
      LocalRegistrationFormat.KeyToken |= *pDataIn++ << 16;
      LocalRegistrationFormat.KeyToken |= *pDataIn++ << 8;
      LocalRegistrationFormat.KeyToken |= *pDataIn++;
      LocalRegistrationFormat.Count = *pDataIn++;
      LocalRegistrationFormat.Date = *pDataIn++;
      LocalRegistrationFormat.StartTimestamp = *pDataIn++ << 24;
      LocalRegistrationFormat.StartTimestamp |= *pDataIn++ << 16;
      LocalRegistrationFormat.StartTimestamp |= *pDataIn++ << 8;
      LocalRegistrationFormat.StartTimestamp |= *pDataIn++;
      LocalRegistrationFormat.EndTimestamp = *pDataIn++ << 24;
      LocalRegistrationFormat.EndTimestamp |= *pDataIn++ << 16;
      LocalRegistrationFormat.EndTimestamp |= *pDataIn++ << 8;
      LocalRegistrationFormat.EndTimestamp |= *pDataIn++;
      for (uint8_t i = 0; i < MAX_TIME_SLOTS; i++)
      {
        LocalRegistrationFormat.TimePeriod[i].StartHour = *pDataIn++;
        LocalRegistrationFormat.TimePeriod[i].StartMinute = *pDataIn++;
        LocalRegistrationFormat.TimePeriod[i].EndHour = *pDataIn++;
        LocalRegistrationFormat.TimePeriod[i].EndMinute = *pDataIn++;
      }
      memcpy(LocalRegistrationFormat.AdministratorPassword, pDataIn, NUMBER_OF_KEYBOARD_KEY);
      pDataIn += NUMBER_OF_KEYBOARD_KEY;

      ProtocolGetSuperAdministratorPassword(AdminPassword);
      if (memcmp(LocalRegistrationFormat.AdministratorPassword, AdminPassword, NUMBER_OF_KEYBOARD_KEY) == 0)
      {
        PraseResult = DEVICE_NOT_AUTHORISED;

        if (ProtocolGetDeviceActivationStatus() == true)
        {
          PraseResult = COMMAND_NOT_SUPPORTED;

          if (ProtocolGetExternalValidationFunctionEnableBit() != true)
          {
            if (ProtocolDetermineIfThisTypeOfKeySupportsLocalRegister(LocalRegistrationFormat.KeyType) == true)
            {
              PraseResult = OVER_OF_SINGLE_USER_REGISTER;

              if (ProtocolGetDirectoryOfAvailableCardholders(LocalRegistrationFormat.UserName) == true)
              {
                PraseResult = TARGET_DEVICE_BUSY;

                if (ProtocolStartLocalRegisterKeyTask(&LocalRegistrationFormat) == true)
                {
                  PraseResult = MESSAGE_PRASE_SUCCESS;
                }
              }
            }
          }
        }
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    memcpy(&pDataOut[ResponseDataLength], LocalRegistrationFormat.UserName, USER_NAME_LENGTH);
    ResponseDataLength += USER_NAME_LENGTH;
    pDataOut[ResponseDataLength++] = LocalRegistrationFormat.KeyType;
    pDataOut[ResponseDataLength++] = (uint8_t)((LocalRegistrationFormat.KeyToken & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((LocalRegistrationFormat.KeyToken & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((LocalRegistrationFormat.KeyToken & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(LocalRegistrationFormat.KeyToken & 0x000000FF);
    pDataOut[ResponseDataLength++] = LocalRegistrationFormat.Count;
    pDataOut[ResponseDataLength++] = LocalRegistrationFormat.Date;
    pDataOut[ResponseDataLength++] = (uint8_t)((LocalRegistrationFormat.StartTimestamp & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((LocalRegistrationFormat.StartTimestamp & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((LocalRegistrationFormat.StartTimestamp & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(LocalRegistrationFormat.StartTimestamp & 0x000000FF);
    pDataOut[ResponseDataLength++] = (uint8_t)((LocalRegistrationFormat.EndTimestamp & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((LocalRegistrationFormat.EndTimestamp & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((LocalRegistrationFormat.EndTimestamp & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(LocalRegistrationFormat.EndTimestamp & 0x000000FF);
    for (uint8_t i = 0; i < MAX_TIME_SLOTS; i++)
    {
      pDataOut[ResponseDataLength++] = LocalRegistrationFormat.TimePeriod[i].StartHour;
      pDataOut[ResponseDataLength++] = LocalRegistrationFormat.TimePeriod[i].StartMinute;
      pDataOut[ResponseDataLength++] = LocalRegistrationFormat.TimePeriod[i].EndHour;
      pDataOut[ResponseDataLength++] = LocalRegistrationFormat.TimePeriod[i].EndMinute;
    }
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingReportLocalRegisterResultMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  if (pSizeOut != NULL)
  {
    *pSizeOut = 0;
  }
}

static void ProtocolParsingBatchNewUsersMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = COMMAND_NOT_SUPPORTED;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingBatchDeleteUsersMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = COMMAND_NOT_SUPPORTED;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingReportingLocalCacheFilePropertiesMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  if (pSizeOut != NULL)
  {
    *pSizeOut = 0;
  }
}

static void ProtocolParsingReportingLocalCacheFilePacketMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  if (pSizeOut != NULL)
  {
    *pSizeOut = 0;
  }
}

static void ProtocolParsingCommandUnlockMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  CommandUnlockFormat_t CommandUnlockFormat = {0};
  uint8_t AdminPassword[NUMBER_OF_KEYBOARD_KEY] = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      CommandUnlockFormat.UnlockingMode = *pDataIn++;
      memcpy(CommandUnlockFormat.AdministratorPassword, pDataIn, NUMBER_OF_KEYBOARD_KEY);
      pDataIn += NUMBER_OF_KEYBOARD_KEY;
      memcpy(CommandUnlockFormat.UserId, pDataIn, USER_AUTHENTICATION_KEY_LENGTH);
      pDataIn += USER_AUTHENTICATION_KEY_LENGTH;

      if ((CommandUnlockFormat.UnlockingMode == DOOR_LOCK) || (CommandUnlockFormat.UnlockingMode == DOOR_UNLOCK) || (CommandUnlockFormat.UnlockingMode == DOOR_NORMAL_OPEN))
      {
        PraseResult = DEVICE_NOT_AUTHORISED;

        if (ProtocolGetDeviceActivationStatus() == true)
        {
          PraseResult = PERMISSION_DENIED;

          ProtocolGetSuperAdministratorPassword(AdminPassword);
          if (memcmp(CommandUnlockFormat.AdministratorPassword, AdminPassword, NUMBER_OF_KEYBOARD_KEY) == 0)
          {
            if (CommandUnlockFormat.UnlockingMode == DOOR_NORMAL_OPEN)
            {
              if (ProtocolGetNormalOpenEn() == false)
              {
                CommandUnlockFormat.UnlockingMode = DOOR_UNLOCK;
              }
            }

            {
              PraseResult = TARGET_DEVICE_BUSY;

              if (ProtocolExecuteCommandToUnlock(CommandUnlockFormat.UserId, CommandUnlockFormat.UnlockingMode) == true)
              {
                PraseResult = MESSAGE_PRASE_SUCCESS;
              }
            }
          }
        }
      }

      if (PraseResult == MESSAGE_PRASE_SUCCESS)
      {
        ProtocolWriteCommandUnlockExecuteResultLog(CommandUnlockFormat.UserId, true);
      }
      else
      {
        ProtocolRemindersInsufficientAuthority();
        ProtocolWriteCommandUnlockExecuteResultLog(CommandUnlockFormat.UserId, false);
      }
    }
  }

  if (pDataOut != NULL)
  {
    CommandUnlockFormat.BatteryCapacity = ProtocolGetVoltagePercentage();
    CommandUnlockFormat.SignalQuality = ProtocolGetWirelessCommunicationQuality();

    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = CommandUnlockFormat.UnlockingMode;
    pDataOut[ResponseDataLength++] = CommandUnlockFormat.BatteryCapacity;
    pDataOut[ResponseDataLength++] = CommandUnlockFormat.SignalQuality;
    memcpy(&pDataOut[ResponseDataLength], CommandUnlockFormat.UserId, USER_AUTHENTICATION_KEY_LENGTH);
    ResponseDataLength += USER_AUTHENTICATION_KEY_LENGTH;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingQrcodeUnlockMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  QrCodeDoorOpenFormat_t QrCodeDoorOpenFormat = {0};
  uint8_t AdminPassword[NUMBER_OF_KEYBOARD_KEY] = {0};

  if (pDataIn != NULL)
  {
    if (SizeIn > 0)
    {
      QrCodeDoorOpenFormat.StartTimestamp = *pDataIn++ << 24;
      QrCodeDoorOpenFormat.StartTimestamp |= *pDataIn++ << 16;
      QrCodeDoorOpenFormat.StartTimestamp |= *pDataIn++ << 8;
      QrCodeDoorOpenFormat.StartTimestamp |= *pDataIn++;
      QrCodeDoorOpenFormat.EndTimeStamp = *pDataIn++ << 24;
      QrCodeDoorOpenFormat.EndTimeStamp |= *pDataIn++ << 16;
      QrCodeDoorOpenFormat.EndTimeStamp |= *pDataIn++ << 8;
      QrCodeDoorOpenFormat.EndTimeStamp |= *pDataIn++;
      memcpy(QrCodeDoorOpenFormat.AdministratorPassword, pDataIn, NUMBER_OF_KEYBOARD_KEY);
      pDataIn += NUMBER_OF_KEYBOARD_KEY;
      memcpy(QrCodeDoorOpenFormat.UserId, pDataIn, USER_AUTHENTICATION_KEY_LENGTH);
      pDataIn += USER_AUTHENTICATION_KEY_LENGTH;

      if (QrCodeDoorOpenFormat.EndTimeStamp >= QrCodeDoorOpenFormat.StartTimestamp)
      {
        uint32_t NowTimestamp = ProtocolGetCurrentTimestamp();

        if (((QrCodeDoorOpenFormat.StartTimestamp <= NowTimestamp) && (QrCodeDoorOpenFormat.EndTimeStamp >= NowTimestamp)) || ((QrCodeDoorOpenFormat.StartTimestamp == 0) && (QrCodeDoorOpenFormat.EndTimeStamp == 0)))
        {
          PraseResult = DEVICE_NOT_AUTHORISED;

          if (ProtocolGetDeviceActivationStatus() == true)
          {
            PraseResult = PERMISSION_DENIED;

            ProtocolGetSuperAdministratorPassword(AdminPassword);
            if (memcmp(QrCodeDoorOpenFormat.AdministratorPassword, AdminPassword, NUMBER_OF_KEYBOARD_KEY) == 0)
            {
              PraseResult = MESSAGE_PRASE_SUCCESS;
            }
          }
        }
      }

      if (PraseResult == MESSAGE_PRASE_SUCCESS)
      {
        ProtocolExecuteQrCodeToUnLock(QrCodeDoorOpenFormat.UserId);
        ProtocolWriteQrUnlockExecuteResultLog(QrCodeDoorOpenFormat.UserId, true);
      }
      else
      {
        ProtocolRemindersInsufficientAuthority();
        ProtocolWriteQrUnlockExecuteResultLog(QrCodeDoorOpenFormat.UserId, false);
      }
    }
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = 0;
  }
}

static void ProtocolParsingQrcodePatrolMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
}

static void ProtocolParsingBluetoothVirtualCardMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  BluetoothVirtualCardFormat_t BluetoothVirtualCardFormat = {0};

  if (pDataIn != NULL)
  {

    if (SizeIn > 0)
    {
      BluetoothVirtualCardFormat.CreationTime = *pDataIn++ << 24;
      BluetoothVirtualCardFormat.CreationTime |= *pDataIn++ << 16;
      BluetoothVirtualCardFormat.CreationTime |= *pDataIn++ << 8;
      BluetoothVirtualCardFormat.CreationTime |= *pDataIn++;
      memcpy(BluetoothVirtualCardFormat.UserName, pDataIn, USER_NAME_LENGTH);
      pDataIn += USER_NAME_LENGTH;
      memcpy(BluetoothVirtualCardFormat.KeyValue, pDataIn, USER_AUTHENTICATION_KEY_LENGTH);
      pDataIn += USER_AUTHENTICATION_KEY_LENGTH;
      BluetoothVirtualCardFormat.StartTimestamp = *pDataIn++ << 24;
      BluetoothVirtualCardFormat.StartTimestamp |= *pDataIn++ << 16;
      BluetoothVirtualCardFormat.StartTimestamp |= *pDataIn++ << 8;
      BluetoothVirtualCardFormat.StartTimestamp |= *pDataIn++;
      BluetoothVirtualCardFormat.EndTimestamp = *pDataIn++ << 24;
      BluetoothVirtualCardFormat.EndTimestamp |= *pDataIn++ << 16;
      BluetoothVirtualCardFormat.EndTimestamp |= *pDataIn++ << 8;
      BluetoothVirtualCardFormat.EndTimestamp |= *pDataIn++;
      BluetoothVirtualCardFormat.Date = *pDataIn++;
      for (uint8_t i = 0; i < MAX_TIME_SLOTS; i++)
      {
        BluetoothVirtualCardFormat.TimePeriod[i].StartHour = *pDataIn++;
        BluetoothVirtualCardFormat.TimePeriod[i].StartMinute = *pDataIn++;
        BluetoothVirtualCardFormat.TimePeriod[i].EndHour = *pDataIn++;
        BluetoothVirtualCardFormat.TimePeriod[i].EndMinute = *pDataIn++;
      }

      BluetoothVirtualCardFormat.AuthorizationCode = *pDataIn++ << 24;
      BluetoothVirtualCardFormat.AuthorizationCode |= *pDataIn++ << 16;
      BluetoothVirtualCardFormat.AuthorizationCode |= *pDataIn++ << 8;
      BluetoothVirtualCardFormat.AuthorizationCode |= *pDataIn++;
      BluetoothVirtualCardFormat.BatteryValue = ProtocolGetVoltagePercentage();

      PraseResult = DEVICE_NOT_AUTHORISED;

      if (ProtocolGetDeviceActivationStatus() == true)
      {
        PraseResult = ProtocolAnalyzingBluetoothVirtualCards(&BluetoothVirtualCardFormat);
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    memcpy(&pDataOut[ResponseDataLength], BluetoothVirtualCardFormat.UserName, USER_NAME_LENGTH);
    ResponseDataLength += USER_NAME_LENGTH;
    memcpy(&pDataOut[ResponseDataLength], BluetoothVirtualCardFormat.KeyValue, USER_AUTHENTICATION_KEY_LENGTH);
    ResponseDataLength += USER_AUTHENTICATION_KEY_LENGTH;
    pDataOut[ResponseDataLength++] = (uint8_t)((BluetoothVirtualCardFormat.StartTimestamp & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((BluetoothVirtualCardFormat.StartTimestamp & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((BluetoothVirtualCardFormat.StartTimestamp & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(BluetoothVirtualCardFormat.StartTimestamp & 0x000000FF);
    pDataOut[ResponseDataLength++] = (uint8_t)((BluetoothVirtualCardFormat.EndTimestamp & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((BluetoothVirtualCardFormat.EndTimestamp & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((BluetoothVirtualCardFormat.EndTimestamp & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(BluetoothVirtualCardFormat.EndTimestamp & 0x000000FF);
    pDataOut[ResponseDataLength++] = BluetoothVirtualCardFormat.Date;
    for (uint8_t i = 0; i < MAX_TIME_SLOTS; i++)
    {
      pDataOut[ResponseDataLength++] = BluetoothVirtualCardFormat.TimePeriod[i].StartHour;
      pDataOut[ResponseDataLength++] = BluetoothVirtualCardFormat.TimePeriod[i].StartMinute;
      pDataOut[ResponseDataLength++] = BluetoothVirtualCardFormat.TimePeriod[i].EndHour;
      pDataOut[ResponseDataLength++] = BluetoothVirtualCardFormat.TimePeriod[i].EndMinute;
    }

    pDataOut[ResponseDataLength++] = (uint8_t)((BluetoothVirtualCardFormat.AuthorizationCode & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((BluetoothVirtualCardFormat.AuthorizationCode & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((BluetoothVirtualCardFormat.AuthorizationCode & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(BluetoothVirtualCardFormat.AuthorizationCode & 0x000000FF);
    pDataOut[ResponseDataLength++] = BluetoothVirtualCardFormat.BatteryValue;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingNetworkAttachmentMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  char TmpDataBuff[100] = {0};
  uint8_t PraseResult = OPERATION_FAILURE;
  uint16_t ServerConnectPort = 0, ResponseDataLength = 0;
  NetworkAttributeDataPacket_t NetworkAttributeDataPacket = {0};
  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;
    if (SizeIn > 0)
    {
      PraseResult = COMMAND_NOT_SUPPORTED;
      if (ProtocolGetCat1FunctionEnableBit() == true)
      {
        NetworkAttributeDataPacket.PacketSize = *pDataIn++ << 8;
        NetworkAttributeDataPacket.PacketSize |= *pDataIn++;
        if (NetworkAttributeDataPacket.PacketSize <= PROTOCOL_ATTACHED_DATA_LENGTH)
        {
          PraseResult = MESSAGE_PRASE_SUCCESS;
          if (NetworkAttributeDataPacket.PacketSize > 0)
          {
            memcpy(NetworkAttributeDataPacket.PacketData, pDataIn, NetworkAttributeDataPacket.PacketSize);
            pDataIn += NetworkAttributeDataPacket.PacketSize;
            bool SubcommandParseStatus = true;
            uint8_t MessageCmd = 0, MessgaeSize = 0;
            uint8_t *pMessageStart = NULL, *pMessageEnd = NULL;
            uint8_t SetNetFg=0;
            pMessageStart = NetworkAttributeDataPacket.PacketData;
            pMessageEnd = NetworkAttributeDataPacket.PacketData + NetworkAttributeDataPacket.PacketSize;
            
            while (pMessageStart < pMessageEnd)
            {
              MessageCmd = pMessageStart[0];
              MessgaeSize = pMessageStart[1];

              memset(TmpDataBuff, 0, 40);
              memcpy(TmpDataBuff, &pMessageStart[2], MessgaeSize);
              printf("MessageCmd %02x \r\n",MessageCmd);
              switch (MessageCmd)
              {
              case SUBCOMMAND_DNS_CODEING:
                SubcommandParseStatus = ProtocolSetDnsServerAddress(TmpDataBuff);
                break;

              case SUBCOMMAND_DOMAIN_NAME_CODEING:
                SubcommandParseStatus = ProtocolSetTheDomainNameOfTheServer(TmpDataBuff);
                break;

              case SUBCOMMAND_SERVER_PORT_CODEING:
                ServerConnectPort = (pMessageStart[2] << 8) | pMessageStart[3];
                SubcommandParseStatus = ProtocolSetTheServerConnectionPort(ServerConnectPort);
                break;

              case SUBCOMMAND_MQTT_USER_NAME_CODEING:
                SubcommandParseStatus = ProtocolSetMqttUserName(TmpDataBuff);
                break;

              case SUBCOMMAND_MQTT_PASSWORD_CODEING:
                SubcommandParseStatus = ProtocolSetMqttAccessPassword(TmpDataBuff);
                break;

              case SUBCOMMAND_MQTT_SUBSCRIBE_TOPICS_CODEING:
                SubcommandParseStatus = ProtocolSetMqttSubscriptioTopic(TmpDataBuff);
                break;

              case SUBCOMMAND_MQTT_PUBLISH_TOPICS_CODEING:
                SubcommandParseStatus = ProtocolSetMqttPublishTopic(TmpDataBuff);
                break;

              case SUBCOMMAND_TARGET_SERVER_CONNECT_IP_ADDRESS:
                SubcommandParseStatus = ProtocolSetTargetServerConnectionIpAddress(TmpDataBuff);
                break;
              case SUBCOMMAND_TARGET_WIFI_SSID:
                printf("write SSID\r\n");
                SetNetFg=1;
                SubcommandParseStatus = ProtocolSetWifiSsid(TmpDataBuff);
                break;

              case SUBCOMMAND_TARGET_WIFI_PW:
                printf("write pw\r\n");
                SubcommandParseStatus = ProtocolSetWifiPassword(TmpDataBuff);
                break;

              case SUBCOMMAND_LOOK_MAC:
                printf("write mac\r\n");
                SubcommandParseStatus = ProtocolSetLockMac(TmpDataBuff);
                break;
              
              }

              pMessageStart += MessgaeSize + 2;
              if (SubcommandParseStatus == false)
                break;
            }

            if (SubcommandParseStatus != true)
            {
              ProtocolLoadDeviceParametersFromMemory();
              PraseResult = MESSAGE_ERROR_DELIVER_PARAM;
            }
            else
            {
              ProtocolUpdateDeviceParamete();
              if(SetNetFg)
              {
                Start_SendNetJump_Task();
              } 
            }
          }
        }

        if (PraseResult == MESSAGE_PRASE_SUCCESS)
        {
          NetworkAttributeDataPacket.PacketSize = 0;

          memset(TmpDataBuff, 0, 40);
          ProtocolGetDnsServerAddress(TmpDataBuff);
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = SUBCOMMAND_DNS_CODEING;
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = NUMBER_OF_SERVER_IP_ADDRESS;
          memcpy(&NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize], TmpDataBuff, NUMBER_OF_SERVER_IP_ADDRESS);
          NetworkAttributeDataPacket.PacketSize += NUMBER_OF_SERVER_IP_ADDRESS;

          memset(TmpDataBuff, 0, 40);
          ProtocolObtainTheServerDomainAddress(TmpDataBuff);
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = SUBCOMMAND_DOMAIN_NAME_CODEING;
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = strlen(TmpDataBuff);
          memcpy(&NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize], TmpDataBuff, strlen(TmpDataBuff));
          NetworkAttributeDataPacket.PacketSize += strlen(TmpDataBuff);

          ServerConnectPort = ProtocolGetTheServerConnectionPort();
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = SUBCOMMAND_SERVER_PORT_CODEING;
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = 2;
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = (uint8_t)((ServerConnectPort & 0xFF00) >> 8);
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = (uint8_t)(ServerConnectPort & 0xFF);

          memset(TmpDataBuff, 0, 40);
          ProtocolGetMqttUserName(TmpDataBuff);
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = SUBCOMMAND_MQTT_USER_NAME_CODEING;
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = strlen(TmpDataBuff);
          memcpy(&NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize], TmpDataBuff, strlen(TmpDataBuff));
          NetworkAttributeDataPacket.PacketSize += strlen(TmpDataBuff);

          memset(TmpDataBuff, 0, 40);
          ProtocolGetMqttAccessPassword(TmpDataBuff);
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = SUBCOMMAND_MQTT_PASSWORD_CODEING;
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = strlen(TmpDataBuff);
          memcpy(&NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize], TmpDataBuff, strlen(TmpDataBuff));
          NetworkAttributeDataPacket.PacketSize += strlen(TmpDataBuff);

          memset(TmpDataBuff, 0, 40);
          ProtocolGetMqttSubscriptioTopic(TmpDataBuff);
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = SUBCOMMAND_MQTT_SUBSCRIBE_TOPICS_CODEING;
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = strlen(TmpDataBuff);
          memcpy(&NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize], TmpDataBuff, strlen(TmpDataBuff));
          NetworkAttributeDataPacket.PacketSize += strlen(TmpDataBuff);

          memset(TmpDataBuff, 0, 40);
          ProtocolGetMqttPublishTopic(TmpDataBuff);
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = SUBCOMMAND_MQTT_PUBLISH_TOPICS_CODEING;
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = strlen(TmpDataBuff);
          memcpy(&NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize], TmpDataBuff, strlen(TmpDataBuff));
          NetworkAttributeDataPacket.PacketSize += strlen(TmpDataBuff);

          memset(TmpDataBuff, 0, 40);
          ProtocolGetTargetServerConnectionIpAddress(TmpDataBuff);
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = SUBCOMMAND_TARGET_SERVER_CONNECT_IP_ADDRESS;
          NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize++] = NUMBER_OF_SERVER_IP_ADDRESS;
          memcpy(&NetworkAttributeDataPacket.PacketData[NetworkAttributeDataPacket.PacketSize], TmpDataBuff, NUMBER_OF_SERVER_IP_ADDRESS);
          NetworkAttributeDataPacket.PacketSize += NUMBER_OF_SERVER_IP_ADDRESS;
        }
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = (uint8_t)((NetworkAttributeDataPacket.PacketSize & 0xFF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(NetworkAttributeDataPacket.PacketSize & 0x00FF);
    memcpy(&pDataOut[ResponseDataLength], NetworkAttributeDataPacket.PacketData, NetworkAttributeDataPacket.PacketSize);
    ResponseDataLength += NetworkAttributeDataPacket.PacketSize;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingOfIssuedDocumentsMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  PropertieOfIssuedDocumentsFormat_t PropertieOfIssuedDocumentsFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      PropertieOfIssuedDocumentsFormat.FileType = *pDataIn++;
      PropertieOfIssuedDocumentsFormat.FileSize = *pDataIn++ << 24;
      PropertieOfIssuedDocumentsFormat.FileSize |= *pDataIn++ << 16;
      PropertieOfIssuedDocumentsFormat.FileSize |= *pDataIn++ << 8;
      PropertieOfIssuedDocumentsFormat.FileSize |= *pDataIn++;

      switch (PropertieOfIssuedDocumentsFormat.FileType)
      {
      case FILE_FACE_PICTURE:
      case FILE_FACE_EIGENVALUE:
      case FILE_FINGER_EIGENVALUE:
      case FILE_UPDATE_FIEMWARE_PACKET:
      {
        if (PropertieOfIssuedDocumentsFormat.FileType != FILE_UPDATE_FIEMWARE_PACKET)
        {
          PropertieOfIssuedDocumentsFormat.RegisterUsers.TotalFiles = *pDataIn++;
          memcpy(PropertieOfIssuedDocumentsFormat.RegisterUsers.UserName, pDataIn, USER_NAME_LENGTH);
          pDataIn += USER_NAME_LENGTH;
          PropertieOfIssuedDocumentsFormat.RegisterUsers.KeyToken = *pDataIn++ << 24;
          PropertieOfIssuedDocumentsFormat.RegisterUsers.KeyToken |= *pDataIn++ << 16;
          PropertieOfIssuedDocumentsFormat.RegisterUsers.KeyToken |= *pDataIn++ << 8;
          PropertieOfIssuedDocumentsFormat.RegisterUsers.KeyToken |= *pDataIn++;
          PropertieOfIssuedDocumentsFormat.RegisterUsers.Count = *pDataIn++;
          PropertieOfIssuedDocumentsFormat.RegisterUsers.Date = *pDataIn++;
          PropertieOfIssuedDocumentsFormat.RegisterUsers.StartTimestamp = *pDataIn++ << 24;
          PropertieOfIssuedDocumentsFormat.RegisterUsers.StartTimestamp |= *pDataIn++ << 16;
          PropertieOfIssuedDocumentsFormat.RegisterUsers.StartTimestamp |= *pDataIn++ << 8;
          PropertieOfIssuedDocumentsFormat.RegisterUsers.StartTimestamp |= *pDataIn++;
          PropertieOfIssuedDocumentsFormat.RegisterUsers.EndTimestamp = *pDataIn++ << 24;
          PropertieOfIssuedDocumentsFormat.RegisterUsers.EndTimestamp |= *pDataIn++ << 16;
          PropertieOfIssuedDocumentsFormat.RegisterUsers.EndTimestamp |= *pDataIn++ << 8;
          PropertieOfIssuedDocumentsFormat.RegisterUsers.EndTimestamp |= *pDataIn++;
          for (uint8_t i = 0; i < MAX_TIME_SLOTS; i++)
          {
            PropertieOfIssuedDocumentsFormat.RegisterUsers.TimePeriod[i].StartHour = *pDataIn++;
            PropertieOfIssuedDocumentsFormat.RegisterUsers.TimePeriod[i].StartMinute = *pDataIn++;
            PropertieOfIssuedDocumentsFormat.RegisterUsers.TimePeriod[i].EndHour = *pDataIn++;
            PropertieOfIssuedDocumentsFormat.RegisterUsers.TimePeriod[i].EndMinute = *pDataIn++;
          }

          if (PropertieOfIssuedDocumentsFormat.RegisterUsers.TotalFiles != 0)
          {
            if (ProtocolRecordFeatureValueRegisteredUserInformation(PropertieOfIssuedDocumentsFormat.FileType, PropertieOfIssuedDocumentsFormat.FileSize, &PropertieOfIssuedDocumentsFormat.RegisterUsers) == true)
            {
              if (ProtocolGetOnlineRegisterEn() != true)
              {
                PraseResult = MESSAGE_PRASE_SUCCESS;

                ProtocolIntoOnlineRegisterMode();
                ProtocolReloadOnlineRegisterTimer();
                ProtocolSetOnlineRegisterTotalFiles(PropertieOfIssuedDocumentsFormat.RegisterUsers.TotalFiles);
              }
            }
          }
          else
          {
            PraseResult = MESSAGE_PRASE_SUCCESS;

            ProtocolExitOnlineRegisterMode();
          }
        }
        else
        {
#if 0 
          PraseResult = LOW_BATTERY_ALARM;

          if (ProtocolGetVoltagePercentage() >= PROTOCOL_LOW_VOLTAGE_PROTECTION_THRESHOLD)
          {
            PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

            PropertieOfIssuedDocumentsFormat.Firmware.FileToken = *pDataIn++ << 24;
            PropertieOfIssuedDocumentsFormat.Firmware.FileToken |= *pDataIn++ << 16;
            PropertieOfIssuedDocumentsFormat.Firmware.FileToken |= *pDataIn++ << 8;
            PropertieOfIssuedDocumentsFormat.Firmware.FileToken |= *pDataIn++;

            if (ProtocolIntoFirmwareUpdate(PropertieOfIssuedDocumentsFormat.FileSize) == true)
            {
              ProtocolIntoFirmwareUpdateMode();
              PraseResult = MESSAGE_PRASE_SUCCESS;
            }
          }
#endif
        }
      }
      break;
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = PropertieOfIssuedDocumentsFormat.FileType;
    pDataOut[ResponseDataLength++] = (uint8_t)((PropertieOfIssuedDocumentsFormat.FileSize & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((PropertieOfIssuedDocumentsFormat.FileSize & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((PropertieOfIssuedDocumentsFormat.FileSize & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(PropertieOfIssuedDocumentsFormat.FileSize & 0x000000FF);
    if (PropertieOfIssuedDocumentsFormat.FileType != FILE_UPDATE_FIEMWARE_PACKET)
    {
      pDataOut[ResponseDataLength++] = PropertieOfIssuedDocumentsFormat.RegisterUsers.TotalFiles;
      memcpy(&pDataOut[ResponseDataLength], PropertieOfIssuedDocumentsFormat.RegisterUsers.UserName, USER_NAME_LENGTH);
      ResponseDataLength += USER_NAME_LENGTH;
      pDataOut[ResponseDataLength++] = (uint8_t)((PropertieOfIssuedDocumentsFormat.RegisterUsers.KeyToken & 0xFF000000) >> 24);
      pDataOut[ResponseDataLength++] = (uint8_t)((PropertieOfIssuedDocumentsFormat.RegisterUsers.KeyToken & 0x00FF0000) >> 16);
      pDataOut[ResponseDataLength++] = (uint8_t)((PropertieOfIssuedDocumentsFormat.RegisterUsers.KeyToken & 0x0000FF00) >> 8);
      pDataOut[ResponseDataLength++] = (uint8_t)(PropertieOfIssuedDocumentsFormat.RegisterUsers.KeyToken & 0x000000FF);
      pDataOut[ResponseDataLength++] = PropertieOfIssuedDocumentsFormat.RegisterUsers.Count;
      pDataOut[ResponseDataLength++] = PropertieOfIssuedDocumentsFormat.RegisterUsers.Date;
      pDataOut[ResponseDataLength++] = (uint8_t)((PropertieOfIssuedDocumentsFormat.RegisterUsers.StartTimestamp & 0xFF000000) >> 24);
      pDataOut[ResponseDataLength++] = (uint8_t)((PropertieOfIssuedDocumentsFormat.RegisterUsers.StartTimestamp & 0x00FF0000) >> 16);
      pDataOut[ResponseDataLength++] = (uint8_t)((PropertieOfIssuedDocumentsFormat.RegisterUsers.StartTimestamp & 0x0000FF00) >> 8);
      pDataOut[ResponseDataLength++] = (uint8_t)(PropertieOfIssuedDocumentsFormat.RegisterUsers.StartTimestamp & 0x000000FF);
      pDataOut[ResponseDataLength++] = (uint8_t)((PropertieOfIssuedDocumentsFormat.RegisterUsers.EndTimestamp & 0xFF000000) >> 24);
      pDataOut[ResponseDataLength++] = (uint8_t)((PropertieOfIssuedDocumentsFormat.RegisterUsers.EndTimestamp & 0x00FF0000) >> 16);
      pDataOut[ResponseDataLength++] = (uint8_t)((PropertieOfIssuedDocumentsFormat.RegisterUsers.EndTimestamp & 0x0000FF00) >> 8);
      pDataOut[ResponseDataLength++] = (uint8_t)(PropertieOfIssuedDocumentsFormat.RegisterUsers.EndTimestamp & 0x000000FF);
      for (uint8_t i = 0; i < MAX_TIME_SLOTS; i++)
      {
        pDataOut[ResponseDataLength++] = PropertieOfIssuedDocumentsFormat.RegisterUsers.TimePeriod[i].StartHour;
        pDataOut[ResponseDataLength++] = PropertieOfIssuedDocumentsFormat.RegisterUsers.TimePeriod[i].StartMinute;
        pDataOut[ResponseDataLength++] = PropertieOfIssuedDocumentsFormat.RegisterUsers.TimePeriod[i].EndHour;
        pDataOut[ResponseDataLength++] = PropertieOfIssuedDocumentsFormat.RegisterUsers.TimePeriod[i].EndMinute;
      }
    }
    else
    {
      pDataOut[ResponseDataLength++] = (uint8_t)((PropertieOfIssuedDocumentsFormat.Firmware.FileToken & 0xFF000000) >> 24);
      pDataOut[ResponseDataLength++] = (uint8_t)((PropertieOfIssuedDocumentsFormat.Firmware.FileToken & 0x00FF0000) >> 16);
      pDataOut[ResponseDataLength++] = (uint8_t)((PropertieOfIssuedDocumentsFormat.Firmware.FileToken & 0x0000FF00) >> 8);
      pDataOut[ResponseDataLength++] = (uint8_t)(PropertieOfIssuedDocumentsFormat.Firmware.FileToken & 0x000000FF);
    }
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingIssueDocumentMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  FileDeliveryFormat_t FileDeliveryFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      FileDeliveryFormat.FileType = *pDataIn++;
      FileDeliveryFormat.FileToken = *pDataIn++ << 24;
      FileDeliveryFormat.FileToken |= *pDataIn++ << 16;
      FileDeliveryFormat.FileToken |= *pDataIn++ << 8;
      FileDeliveryFormat.FileToken |= *pDataIn++;
      FileDeliveryFormat.WriteOffset = *pDataIn++ << 24;
      FileDeliveryFormat.WriteOffset |= *pDataIn++ << 16;
      FileDeliveryFormat.WriteOffset |= *pDataIn++ << 8;
      FileDeliveryFormat.WriteOffset |= *pDataIn++;
      FileDeliveryFormat.WritePacketSize = *pDataIn++ << 8;
      FileDeliveryFormat.WritePacketSize |= *pDataIn++;
      memcpy(FileDeliveryFormat.WriteDatePacket, pDataIn, FileDeliveryFormat.WritePacketSize);
      pDataIn += FileDeliveryFormat.WritePacketSize;

      if (FileDeliveryFormat.FileType != FILE_UPDATE_FIEMWARE_PACKET)
      {
        if (FileDeliveryFormat.WritePacketSize <= SINGLE_REQUEST_FILE_LENGTH)
        {
          PraseResult = OPERATION_FAILURE;

          {
            uint32_t EigenvalueFileSize = 0;

            ProtocolReadTheEigenvalueFileInformation(&EigenvalueFileSize, NULL);
            PRINT("[info]: file size: %d, offset: %d, data size: %d.\r\n", EigenvalueFileSize, FileDeliveryFormat.WriteOffset, FileDeliveryFormat.WritePacketSize);

            if (FileDeliveryFormat.WriteOffset <= EigenvalueFileSize)
            {
              if ((FileDeliveryFormat.WritePacketSize > 0) && (FileDeliveryFormat.WritePacketSize <= EigenvalueFileSize))
              {
                if (ProtocolSaveTheEigenvalueFile(FileDeliveryFormat.WriteOffset, FileDeliveryFormat.WriteDatePacket, FileDeliveryFormat.WritePacketSize) == true)
                {
                  PraseResult = MESSAGE_PRASE_SUCCESS;

                  if ((FileDeliveryFormat.WriteOffset + FileDeliveryFormat.WritePacketSize) == EigenvalueFileSize)
                  {
                    ProtocolStartSafetyFeatureValueFileRegistration();
                  }
                  else
                  {
                    ProtocolReloadOnlineRegisterTimer();
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = FileDeliveryFormat.FileType;
    pDataOut[ResponseDataLength++] = (uint8_t)((FileDeliveryFormat.FileToken & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((FileDeliveryFormat.FileToken & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((FileDeliveryFormat.FileToken & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(FileDeliveryFormat.FileToken & 0x000000FF);
    pDataOut[ResponseDataLength++] = (uint8_t)((FileDeliveryFormat.WriteOffset & 0xFF000000) >> 24);
    pDataOut[ResponseDataLength++] = (uint8_t)((FileDeliveryFormat.WriteOffset & 0x00FF0000) >> 16);
    pDataOut[ResponseDataLength++] = (uint8_t)((FileDeliveryFormat.WriteOffset & 0x0000FF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(FileDeliveryFormat.WriteOffset & 0x000000FF);
    pDataOut[ResponseDataLength++] = (uint8_t)((FileDeliveryFormat.WritePacketSize & 0xFF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(FileDeliveryFormat.WritePacketSize & 0x00FF);
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingRealTimeTriggerEventsMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint8_t ResponseCode = 0;
  uint16_t ResponseDataLength = 0;
  RealUploadEventFormat_t RealUploadEventFormat = {0};

  if (pDataIn != NULL)
  {
    if (SizeIn > 0)
    {
      ResponseCode = *pDataIn++;
      if (ResponseCode == MESSAGE_PRASE_SUCCESS)
      {
        RealUploadEventFormat.Type = *pDataIn++;
        RealUploadEventFormat.Parameter = *pDataIn++;
        RealUploadEventFormat.TriggerTime = *pDataIn++ << 24;
        RealUploadEventFormat.TriggerTime |= *pDataIn++ << 16;
        RealUploadEventFormat.TriggerTime |= *pDataIn++ << 8;
        RealUploadEventFormat.TriggerTime |= *pDataIn++;
        memcpy(RealUploadEventFormat.DataPacket, pDataIn, LOG_ATTACHED_DATA_LENGTH);
        pDataIn += LOG_ATTACHED_DATA_LENGTH;
      }
    }
  }
  if (pSizeOut != NULL)
  {
    *pSizeOut = 0;
  }
}

static void ProtocolParsingObtainTheNumberOfLogFilesMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;

  if (pDataOut != NULL)
  {
    ObtainTheNumberOfogFilesFormat_t ObtainTheNumberOfogFilesFormat = {0};
    ObtainTheNumberOfogFilesFormat.NumberOfLogFile = ProtocolGetNumberOfLofFile();

    pDataOut[ResponseDataLength++] = MESSAGE_PRASE_SUCCESS;
    pDataOut[ResponseDataLength++] = (uint8_t)((ObtainTheNumberOfogFilesFormat.NumberOfLogFile & 0xFF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(ObtainTheNumberOfogFilesFormat.NumberOfLogFile & 0x00FF);
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingGetLogFilePacketMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  GetLogFileFormat_t GetLogFileFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      GetLogFileFormat.StartLogTableId = *pDataIn++ << 8;
      GetLogFileFormat.StartLogTableId |= *pDataIn++;
      GetLogFileFormat.NumberOfGet = *pDataIn++;
      PraseResult = ProtocolGetSpecificNumberOfLogFilesFromTheTargetSerialNumber(GetLogFileFormat.StartLogTableId, GetLogFileFormat.NumberOfGet, GetLogFileFormat.LogDataPacket, &GetLogFileFormat.SizeOfLogDataPacket);
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    pDataOut[ResponseDataLength++] = (uint8_t)((GetLogFileFormat.StartLogTableId & 0xFF00) >> 8);
    pDataOut[ResponseDataLength++] = (uint8_t)(GetLogFileFormat.StartLogTableId & 0x00FF);
    pDataOut[ResponseDataLength++] = GetLogFileFormat.NumberOfGet;
    memcpy(&pDataOut[ResponseDataLength], GetLogFileFormat.LogDataPacket, GetLogFileFormat.SizeOfLogDataPacket);
    ResponseDataLength += GetLogFileFormat.SizeOfLogDataPacket;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingPushVendorMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = COMMAND_NOT_SUPPORTED;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingReceivingVendorMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = COMMAND_NOT_SUPPORTED;
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

static void ProtocolParsingExternalValidationMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint8_t ResponseCode = 0;
  ExterlalValidationeFormat_t ExterlalValidatione = {0};

  if (pDataIn != NULL)
  {
    if (SizeIn > 0)
    {
      ResponseCode = *pDataIn++;
      ExterlalValidatione.KeyType = *pDataIn++;
      memcpy(ExterlalValidatione.KeyValue, pDataIn, USER_AUTHENTICATION_KEY_LENGTH);
      pDataIn += USER_AUTHENTICATION_KEY_LENGTH;

      if (ResponseCode == MESSAGE_PRASE_SUCCESS)
      {
        ProtocolExternalHostRequestToUnlock(ExterlalValidatione.KeyType, ExterlalValidatione.KeyValue);
        ProtocolWriteExternalValidationResultLog(ExterlalValidatione.KeyType, ExterlalValidatione.KeyValue, true);
      }
      else
      {
        ProtocolRemindersInsufficientAuthority();
        ProtocolWriteExternalValidationResultLog(ExterlalValidatione.KeyType, ExterlalValidatione.KeyValue, false);
      }
    }
  }
}

static void ProtocolParsingTestMessage(const uint8_t *pDataIn, uint16_t SizeIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  uint16_t ResponseDataLength = 0;
  uint8_t PraseResult = OPERATION_FAILURE;
  ConnectTestFormat_t ConnectTestFormat = {0};

  if (pDataIn != NULL)
  {
    PraseResult = MESSAGE_ERROR_DELIVER_PARAM;

    if (SizeIn > 0)
    {
      ConnectTestFormat.DataLength = *pDataIn++ << 8;
      ConnectTestFormat.DataLength |= *pDataIn++;

      if (ConnectTestFormat.DataLength <= SINGLE_COMMUNICATION_TEST_DATA_LENGTH)
      {
        PraseResult = MESSAGE_PRASE_SUCCESS;

        memcpy(ConnectTestFormat.DataPacket, pDataIn, ConnectTestFormat.DataLength);
        pDataIn += ConnectTestFormat.DataLength;
      }
    }
  }

  if (pDataOut != NULL)
  {
    pDataOut[ResponseDataLength++] = PraseResult;
    if (PraseResult == MESSAGE_PRASE_SUCCESS)
    {
      pDataOut[ResponseDataLength++] = (uint8_t)((ConnectTestFormat.DataLength & 0xFF00) >> 8);
      pDataOut[ResponseDataLength++] = (uint8_t)(ConnectTestFormat.DataLength & 0x00FF);
      memcpy(&pDataOut[ResponseDataLength], ConnectTestFormat.DataPacket, ConnectTestFormat.DataLength);
      ResponseDataLength += ConnectTestFormat.DataLength;

      if (ConnectTestFormat.DataLength == 0)
      {
        ProtocolPlayConnectTestAudio();
      }
    }
  }

  if (pSizeOut != NULL)
  {
    *pSizeOut = ResponseDataLength;
  }
}

uint8_t ProtocolSumCrcCheck(const uint8_t *pDataIn, uint16_t SizeIn)
{
  uint32_t SumVal = 0;

  for (uint16_t i = 0; i < SizeIn; i++)
  {
    SumVal += pDataIn[i];
  }

  return (uint8_t)(SumVal & 0x000000FF);
}

void ProtocolParsingInputMessages(uint8_t *pDataIn, uint16_t DataSize, uint8_t *pDataOut, uint16_t *pSizeOut, uint8_t *pCommandOut, uint32_t *pBasisOfSearchOut)
{
  if ((pDataIn != NULL) && (pDataOut != NULL) && (pSizeOut != NULL))
  {
    if ((DataSize > 0) && (DataSize <= PROTOCOL_LENGTH_OF_SINGLE_MESSAGE_PACKET))
    {
      uint16_t AttaDataSize = 0, ResponseDataLength = 0;
      ProtocolFormat_t *pRxProtocolFormat = (ProtocolFormat_t *)pDataIn;
      ProtocolFormat_t *pTxProtocolFormat = (ProtocolFormat_t *)pDataOut;

      {
        PRINT("[message]: command received, size: %d, data: ", DataSize);
        for (uint16_t i = 0; i < DataSize; i++)
          PRINT("%02X ", pDataIn[i]);
        PRINT("\r\n");

        ProtocolPraseResult_t Result = ProtocolVerifyMessageValidity(pDataIn, DataSize);
        if (Result == MESSAGE_PRASE_SUCCESS)
        {
          PRINT("[message]: command parsed successfully.\r\n");

          AttaDataSize = (pRxProtocolFormat->Length[0] << 8) | pRxProtocolFormat->Length[1];
          ResponseFunction[pRxProtocolFormat->Command](pRxProtocolFormat->Data, AttaDataSize, pTxProtocolFormat->Data, &ResponseDataLength);
        }
        else
        {
          PRINT("[message]: command parsed error, code: %02X.\r\n", Result);
          pTxProtocolFormat->Data[ResponseDataLength++] = Result;
        }
      }

      if (ResponseDataLength != 0)
      {
        {
          uint32_t CurrentTimestamp = 0;
          uint8_t DeviceIdenx[PROTOCOL_INDEX_BIT_LENGTH] = {0};

          ProtocolGetDeviceIndex(DeviceIdenx);
          CurrentTimestamp = ProtocolGetCurrentTimestamp();

          pTxProtocolFormat->Version =  PROTOCOL_VERSION_CONTORL;
          pTxProtocolFormat->Command = pRxProtocolFormat->Command;
          pTxProtocolFormat->SyncwordCode = PROTOCOL_SYNCWORD_CODE;
          pTxProtocolFormat->Length[0] = (uint8_t)((ResponseDataLength & 0xFF00) >> 8);
          pTxProtocolFormat->Length[1] = (uint8_t)(ResponseDataLength & 0x00FF);
          pTxProtocolFormat->TimeStamp[0] = (uint8_t)((CurrentTimestamp & 0xFF000000) >> 24);
          pTxProtocolFormat->TimeStamp[1] = (uint8_t)((CurrentTimestamp & 0x00FF0000) >> 16);
          pTxProtocolFormat->TimeStamp[2] = (uint8_t)((CurrentTimestamp & 0x0000FF00) >> 8);
          pTxProtocolFormat->TimeStamp[3] = (uint8_t)(CurrentTimestamp & 0x000000FF);
          memcpy(pTxProtocolFormat->Index, DeviceIdenx, PROTOCOL_INDEX_BIT_LENGTH);
          memcpy(pTxProtocolFormat->Random, pRxProtocolFormat->Random, PROTOCOL_RANDOM_BIT_LENGTH);
          ProtocolCalculatingCaptchaValue(pTxProtocolFormat->Index, pTxProtocolFormat->Random, pTxProtocolFormat->Captcha);
        }

        {
          if (ProtocolGetEncryptionFunctionEnableBit() == true)
          {
            ResponseDataLength = ProtocolEncryption(pDataOut);
            ResponseDataLength += PROTOCOL_SYNCWORD_BIT_LENGTH + PROTOCOL_DATA_SIZE_BIT_LENGTH;
          }
          else
          {
            ResponseDataLength += PROTOCOL_FIXED_BIT_LENGTH;
          }

          pDataOut[ResponseDataLength] = ProtocolSumCrcCheck(pDataOut, ResponseDataLength);
          ResponseDataLength += PROTOCOL_CHECK_CODE_BIT_LENGTH;

          PRINT("[message]: answer size: %d, data: ", ResponseDataLength);
          for (uint16_t i = 0; i < ResponseDataLength; i++)
            PRINT("%02X", pDataOut[i]);
          PRINT("\r\n");
        }

        {
          *pSizeOut = ResponseDataLength;
        }
      }

      if (pCommandOut != NULL)
      {
        *pCommandOut = pRxProtocolFormat->Command;
      }

      if (pBasisOfSearchOut != NULL)
      {
        uint32_t SearchId = 0;
        SearchId = pRxProtocolFormat->Random[0] << 24;
        SearchId |= pRxProtocolFormat->Random[1] << 16;
        SearchId |= pRxProtocolFormat->Random[2] << 8;
        SearchId |= pRxProtocolFormat->Random[3];

        *pBasisOfSearchOut = SearchId;
      }
    }
  }
}

bool ProtocolBuildHeartbeatMessage(uint8_t DeviceType, uint8_t PercentageOfPower, uint8_t Rssi, uint32_t MessageHandle, uint8_t *pMessageOut, uint16_t *pMessageSizeOut)
{
  ProtocolFormat_t *pTxProtocolFormat = (ProtocolFormat_t *)pMessageOut;

  if (pTxProtocolFormat != NULL)
  {
    uint16_t SendDataLength = 0;
    uint32_t NowTimestamp = ProtocolGetCurrentTimestamp();

    pTxProtocolFormat->Command = SYSTEM_HEARTBEAT_CMD;
    pTxProtocolFormat->Version = PROTOCOL_VERSION_CONTORL;
    pTxProtocolFormat->SyncwordCode = PROTOCOL_SYNCWORD_CODE;
    pTxProtocolFormat->Random[0] = (uint8_t)((MessageHandle & 0xFF000000) >> 24);
    pTxProtocolFormat->Random[1] = (uint8_t)((MessageHandle & 0x00FF0000) >> 16);
    pTxProtocolFormat->Random[2] = (uint8_t)((MessageHandle & 0x0000FF00) >> 8);
    pTxProtocolFormat->Random[3] = (uint8_t)(MessageHandle & 0x000000FF);
    pTxProtocolFormat->TimeStamp[0] = (uint8_t)((NowTimestamp & 0xFF000000) >> 24);
    pTxProtocolFormat->TimeStamp[1] = (uint8_t)((NowTimestamp & 0x00FF0000) >> 16);
    pTxProtocolFormat->TimeStamp[2] = (uint8_t)((NowTimestamp & 0x0000FF00) >> 8);
    pTxProtocolFormat->TimeStamp[3] = (uint8_t)(NowTimestamp & 0x000000FF);
    ProtocolGetDeviceIndex(pTxProtocolFormat->Index);
    ProtocolCalculatingCaptchaValue(pTxProtocolFormat->Index, pTxProtocolFormat->Random, pTxProtocolFormat->Captcha);

    pTxProtocolFormat->Data[SendDataLength++] = DeviceType;
    pTxProtocolFormat->Data[SendDataLength++] = PercentageOfPower;
    pTxProtocolFormat->Data[SendDataLength++] = Rssi;

    pTxProtocolFormat->Length[0] = (uint8_t)((SendDataLength & 0xFF00) >> 8);
    pTxProtocolFormat->Length[1] = (uint8_t)(SendDataLength & 0x00FF);

    if (ProtocolGetEncryptionFunctionEnableBit() == true)
    {
      SendDataLength = ProtocolEncryption(pMessageOut);
      SendDataLength += PROTOCOL_SYNCWORD_BIT_LENGTH + PROTOCOL_DATA_SIZE_BIT_LENGTH;
    }
    else
    {
      SendDataLength += PROTOCOL_FIXED_BIT_LENGTH;
    }

    pMessageOut[SendDataLength] = ProtocolSumCrcCheck(pMessageOut, SendDataLength);
    SendDataLength += PROTOCOL_CHECK_CODE_BIT_LENGTH;

    if (pMessageSizeOut != NULL)
    {
      *pMessageSizeOut = SendDataLength;
    }

    return true;
  }

  return false;
}

bool ProtocolBuildLockOpenMessage(uint32_t MessageHandle, uint8_t *pMessageOut, uint16_t *pMessageSizeOut)
{
  ProtocolFormat_t *pTxProtocolFormat = (ProtocolFormat_t *)pMessageOut;
  uint8_t i=0;
  uint8_t date[100];
  if (pTxProtocolFormat != NULL)
  {
    uint16_t SendDataLength = 0;
    uint32_t NowTimestamp = ProtocolGetCurrentTimestamp();
    uint8_t key[6]={0x31,0x32,0x33,0x34,0x35,0x36};
    uint8_t id[10]={0};
    uint8_t aes[9]={0};
    pTxProtocolFormat->Command = COMMAND_REMOTE_DOOR_OPENING;
    pTxProtocolFormat->Version = PROTOCOL_VERSION_CONTORL;
    pTxProtocolFormat->SyncwordCode = PROTOCOL_SYNCWORD_CODE;
    pTxProtocolFormat->Random[0] = (uint8_t)((MessageHandle & 0xFF000000) >> 24);
    pTxProtocolFormat->Random[1] = (uint8_t)((MessageHandle & 0x00FF0000) >> 16);
    pTxProtocolFormat->Random[2] = (uint8_t)((MessageHandle & 0x0000FF00) >> 8);
    pTxProtocolFormat->Random[3] = (uint8_t)(MessageHandle & 0x000000FF);
    pTxProtocolFormat->TimeStamp[0] = (uint8_t)((NowTimestamp & 0xFF000000) >> 24);
    pTxProtocolFormat->TimeStamp[1] = (uint8_t)((NowTimestamp & 0x00FF0000) >> 16);
    pTxProtocolFormat->TimeStamp[2] = (uint8_t)((NowTimestamp & 0x0000FF00) >> 8);
    pTxProtocolFormat->TimeStamp[3] = (uint8_t)(NowTimestamp & 0x000000FF);
    ProtocolGetDoorDeviceIndex(pTxProtocolFormat->Index);
    printf("send door mac :");
      for(i=0;i<8;i++)
      {
        printf("%02x ",pTxProtocolFormat->Index[i]);
      }
    ProtocolCalculatingCaptchaValue(pTxProtocolFormat->Index, pTxProtocolFormat->Random, pTxProtocolFormat->Captcha);
    pTxProtocolFormat->Length[1] = (uint8_t)(SendDataLength & 0x00FF);
    pTxProtocolFormat->Data[0]=DOOR_UNLOCK;
    memcpy(&pTxProtocolFormat->Data[1],key,6);
    memcpy(&pTxProtocolFormat->Data[7],id,10);
    memcpy(&pTxProtocolFormat->Data[17],aes,9);
    SendDataLength=(1+6+10+9);
    pTxProtocolFormat->Length[0] = ((SendDataLength & 0xFF00) >> 8);
    pTxProtocolFormat->Length[1] = (SendDataLength & 0x00FF);
    memcpy(date,pTxProtocolFormat,100);
    if (ProtocolGetEncryptionFunctionEnableBit() == true)
    {
      SendDataLength = ProtocolEncryption(pMessageOut);
      SendDataLength += PROTOCOL_SYNCWORD_BIT_LENGTH + PROTOCOL_DATA_SIZE_BIT_LENGTH;
    }
    else
    {
      SendDataLength += PROTOCOL_FIXED_BIT_LENGTH;
    }

    pMessageOut[SendDataLength] = ProtocolSumCrcCheck(pMessageOut, SendDataLength);
    SendDataLength += PROTOCOL_CHECK_CODE_BIT_LENGTH;

    if (pMessageSizeOut != NULL)
    {
      *pMessageSizeOut = SendDataLength;
    }

    return true;
  }

  return false;
}

bool ProtocolBuildLocalRegisterResultMessage(ReportCardholderInformationFormat_t *pInformationIn, uint8_t Result, uint32_t MessageHandle, uint8_t *pMessageOut, uint16_t *pMessageSizeOut)
{
  ProtocolFormat_t *pTxProtocolFormat = (ProtocolFormat_t *)pMessageOut;

  if ((pTxProtocolFormat != NULL) && (pInformationIn != NULL))
  {
    uint16_t SendDataLength = 0;
    uint32_t NowTimestamp = ProtocolGetCurrentTimestamp();

    pTxProtocolFormat->Version = PROTOCOL_VERSION_CONTORL;
    pTxProtocolFormat->SyncwordCode = PROTOCOL_SYNCWORD_CODE;
    pTxProtocolFormat->Command = CARDHOLDER_REGISTERED_INFORMATION;
    pTxProtocolFormat->Random[0] = (uint8_t)((MessageHandle & 0xFF000000) >> 24);
    pTxProtocolFormat->Random[1] = (uint8_t)((MessageHandle & 0x00FF0000) >> 16);
    pTxProtocolFormat->Random[2] = (uint8_t)((MessageHandle & 0x0000FF00) >> 8);
    pTxProtocolFormat->Random[3] = (uint8_t)(MessageHandle & 0x000000FF);
    pTxProtocolFormat->TimeStamp[0] = (uint8_t)((NowTimestamp & 0xFF000000) >> 24);
    pTxProtocolFormat->TimeStamp[1] = (uint8_t)((NowTimestamp & 0x00FF0000) >> 16);
    pTxProtocolFormat->TimeStamp[2] = (uint8_t)((NowTimestamp & 0x0000FF00) >> 8);
    pTxProtocolFormat->TimeStamp[3] = (uint8_t)(NowTimestamp & 0x000000FF);
    ProtocolGetDeviceIndex(pTxProtocolFormat->Index);
    ProtocolCalculatingCaptchaValue(pTxProtocolFormat->Index, pTxProtocolFormat->Random, pTxProtocolFormat->Captcha);

    memcpy(&pTxProtocolFormat->Data[SendDataLength], pInformationIn->UserName, USER_NAME_LENGTH);
    SendDataLength += USER_NAME_LENGTH;
    pTxProtocolFormat->Data[SendDataLength++] = pInformationIn->KeyType;
    pTxProtocolFormat->Data[SendDataLength++] = (uint8_t)((pInformationIn->KeyToken & 0xFF000000) >> 24);
    pTxProtocolFormat->Data[SendDataLength++] = (uint8_t)((pInformationIn->KeyToken & 0x00FF0000) >> 16);
    pTxProtocolFormat->Data[SendDataLength++] = (uint8_t)((pInformationIn->KeyToken & 0x0000FF00) >> 8);
    pTxProtocolFormat->Data[SendDataLength++] = (uint8_t)(pInformationIn->KeyToken & 0x000000FF);
    memcpy(&pTxProtocolFormat->Data[SendDataLength], pInformationIn->KeyValue, USER_AUTHENTICATION_KEY_LENGTH);
    SendDataLength += USER_AUTHENTICATION_KEY_LENGTH;
    pTxProtocolFormat->Data[SendDataLength++] = pInformationIn->Count;
    pTxProtocolFormat->Data[SendDataLength++] = pInformationIn->Date;
    pTxProtocolFormat->Data[SendDataLength++] = (uint8_t)((pInformationIn->StartTimestamp & 0xFF000000) >> 24);
    pTxProtocolFormat->Data[SendDataLength++] = (uint8_t)((pInformationIn->StartTimestamp & 0x00FF0000) >> 16);
    pTxProtocolFormat->Data[SendDataLength++] = (uint8_t)((pInformationIn->StartTimestamp & 0x0000FF00) >> 8);
    pTxProtocolFormat->Data[SendDataLength++] = (uint8_t)(pInformationIn->StartTimestamp & 0x000000FF);
    pTxProtocolFormat->Data[SendDataLength++] = (uint8_t)((pInformationIn->EndTimestamp & 0xFF000000) >> 24);
    pTxProtocolFormat->Data[SendDataLength++] = (uint8_t)((pInformationIn->EndTimestamp & 0x00FF0000) >> 16);
    pTxProtocolFormat->Data[SendDataLength++] = (uint8_t)((pInformationIn->EndTimestamp & 0x0000FF00) >> 8);
    pTxProtocolFormat->Data[SendDataLength++] = (uint8_t)(pInformationIn->EndTimestamp & 0x000000FF);
    for (uint8_t i = 0; i < MAX_TIME_SLOTS; i++)
    {
      pTxProtocolFormat->Data[SendDataLength++] = pInformationIn->TimePeriod[i].StartHour;
      pTxProtocolFormat->Data[SendDataLength++] = pInformationIn->TimePeriod[i].StartMinute;
      pTxProtocolFormat->Data[SendDataLength++] = pInformationIn->TimePeriod[i].EndHour;
      pTxProtocolFormat->Data[SendDataLength++] = pInformationIn->TimePeriod[i].EndMinute;
    }
    pTxProtocolFormat->Data[SendDataLength++] = Result;

    pTxProtocolFormat->Length[0] = (uint8_t)((SendDataLength & 0xFF00) >> 8);
    pTxProtocolFormat->Length[1] = (uint8_t)(SendDataLength & 0x00FF);

    if (ProtocolGetEncryptionFunctionEnableBit() == true)
    {
      SendDataLength = ProtocolEncryption(pMessageOut);
      SendDataLength += PROTOCOL_SYNCWORD_BIT_LENGTH + PROTOCOL_DATA_SIZE_BIT_LENGTH;
    }
    else
    {
      SendDataLength += PROTOCOL_FIXED_BIT_LENGTH;
    }

    pMessageOut[SendDataLength] = ProtocolSumCrcCheck(pMessageOut, SendDataLength);
    SendDataLength += PROTOCOL_CHECK_CODE_BIT_LENGTH;

    if (pMessageSizeOut != NULL)
    {
      *pMessageSizeOut = SendDataLength;
    }

    return true;
  }

  return false;
}

bool ProtocolBuildIncidentReportingMessage(RealUploadEventFormat_t *pEventInformationIn, uint32_t MessageHandle, uint8_t *pMessageOut, uint16_t *pMessageSizeOut)
{
  ProtocolFormat_t *pTxProtocolFormat = (ProtocolFormat_t *)pMessageOut;

  if ((pTxProtocolFormat != NULL) && (pEventInformationIn != NULL))
  {
    uint16_t SendDataLength = 0;
    uint32_t NowTimestamp = ProtocolGetCurrentTimestamp();

    pTxProtocolFormat->Version = PROTOCOL_VERSION_CONTORL;
    pTxProtocolFormat->SyncwordCode = PROTOCOL_SYNCWORD_CODE;
    pTxProtocolFormat->Command = LOG_REAL_TIME_EVENT_REPORTING;
    pTxProtocolFormat->Random[0] = (uint8_t)((MessageHandle & 0xFF000000) >> 24);
    pTxProtocolFormat->Random[1] = (uint8_t)((MessageHandle & 0x00FF0000) >> 16);
    pTxProtocolFormat->Random[2] = (uint8_t)((MessageHandle & 0x0000FF00) >> 8);
    pTxProtocolFormat->Random[3] = (uint8_t)(MessageHandle & 0x000000FF);
    pTxProtocolFormat->TimeStamp[0] = (uint8_t)((NowTimestamp & 0xFF000000) >> 24);
    pTxProtocolFormat->TimeStamp[1] = (uint8_t)((NowTimestamp & 0x00FF0000) >> 16);
    pTxProtocolFormat->TimeStamp[2] = (uint8_t)((NowTimestamp & 0x0000FF00) >> 8);
    pTxProtocolFormat->TimeStamp[3] = (uint8_t)(NowTimestamp & 0x000000FF);
    ProtocolGetDeviceIndex(pTxProtocolFormat->Index);
    ProtocolCalculatingCaptchaValue(pTxProtocolFormat->Index, pTxProtocolFormat->Random, pTxProtocolFormat->Captcha);

    pTxProtocolFormat->Data[SendDataLength++] = pEventInformationIn->Type;
    pTxProtocolFormat->Data[SendDataLength++] = pEventInformationIn->Parameter;
    pTxProtocolFormat->Data[SendDataLength++] = (uint8_t)((pEventInformationIn->TriggerTime & 0xFF000000) >> 24);
    pTxProtocolFormat->Data[SendDataLength++] = (uint8_t)((pEventInformationIn->TriggerTime & 0x00FF0000) >> 16);
    pTxProtocolFormat->Data[SendDataLength++] = (uint8_t)((pEventInformationIn->TriggerTime & 0x0000FF00) >> 8);
    pTxProtocolFormat->Data[SendDataLength++] = (uint8_t)(pEventInformationIn->TriggerTime & 0x000000FF);
    memcpy(&pTxProtocolFormat->Data[SendDataLength], pEventInformationIn->DataPacket, LOG_ATTACHED_DATA_LENGTH);
    SendDataLength += LOG_ATTACHED_DATA_LENGTH;

    pTxProtocolFormat->Length[0] = (uint8_t)((SendDataLength & 0xFF00) >> 8);
    pTxProtocolFormat->Length[1] = (uint8_t)(SendDataLength & 0x00FF);

    if (ProtocolGetEncryptionFunctionEnableBit() == true)
    {
      SendDataLength = ProtocolEncryption(pMessageOut);
      SendDataLength += PROTOCOL_SYNCWORD_BIT_LENGTH + PROTOCOL_DATA_SIZE_BIT_LENGTH;
    }
    else
    {
      SendDataLength += PROTOCOL_FIXED_BIT_LENGTH;
    }

    pMessageOut[SendDataLength] = ProtocolSumCrcCheck(pMessageOut, SendDataLength);
    SendDataLength += PROTOCOL_CHECK_CODE_BIT_LENGTH;

    if (pMessageSizeOut != NULL)
    {
      *pMessageSizeOut = SendDataLength;
    }

    return true;
  }

  return false;
}

bool ProtocolBuildExternalHostValidationMessage(ExterlalValidationeFormat_t *pExterlalValidationeIn, uint32_t MessageHandle, uint8_t *pMessageOut, uint16_t *pMessageSizeOut)
{
  ProtocolFormat_t *pTxProtocolFormat = (ProtocolFormat_t *)pMessageOut;

  if ((pTxProtocolFormat != NULL) && (pExterlalValidationeIn != NULL))
  {
    uint16_t SendDataLength = 0;
    uint32_t NowTimestamp = ProtocolGetCurrentTimestamp();

    pTxProtocolFormat->Version = PROTOCOL_VERSION_CONTORL;
    pTxProtocolFormat->SyncwordCode = PROTOCOL_SYNCWORD_CODE;
    pTxProtocolFormat->Command = OTHER_EXTERL_HOST_VALIDATION;
    pTxProtocolFormat->Random[0] = (uint8_t)((MessageHandle & 0xFF000000) >> 24);
    pTxProtocolFormat->Random[1] = (uint8_t)((MessageHandle & 0x00FF0000) >> 16);
    pTxProtocolFormat->Random[2] = (uint8_t)((MessageHandle & 0x0000FF00) >> 8);
    pTxProtocolFormat->Random[3] = (uint8_t)(MessageHandle & 0x000000FF);
    pTxProtocolFormat->TimeStamp[0] = (uint8_t)((NowTimestamp & 0xFF000000) >> 24);
    pTxProtocolFormat->TimeStamp[1] = (uint8_t)((NowTimestamp & 0x00FF0000) >> 16);
    pTxProtocolFormat->TimeStamp[2] = (uint8_t)((NowTimestamp & 0x0000FF00) >> 8);
    pTxProtocolFormat->TimeStamp[3] = (uint8_t)(NowTimestamp & 0x000000FF);
    ProtocolGetDeviceIndex(pTxProtocolFormat->Index);
    ProtocolCalculatingCaptchaValue(pTxProtocolFormat->Index, pTxProtocolFormat->Random, pTxProtocolFormat->Captcha);

    pTxProtocolFormat->Data[SendDataLength++] = pExterlalValidationeIn->KeyType;
    memcpy(&pTxProtocolFormat->Data[SendDataLength], pExterlalValidationeIn->KeyValue, TYPE_THE_LENGTH_OF_KEY);
    SendDataLength += TYPE_THE_LENGTH_OF_KEY;

    pTxProtocolFormat->Length[0] = (uint8_t)((SendDataLength & 0xFF00) >> 8);
    pTxProtocolFormat->Length[1] = (uint8_t)(SendDataLength & 0x00FF);

    if (ProtocolGetEncryptionFunctionEnableBit() == true)
    {
      SendDataLength = ProtocolEncryption(pMessageOut);
      SendDataLength += PROTOCOL_SYNCWORD_BIT_LENGTH + PROTOCOL_DATA_SIZE_BIT_LENGTH;
    }
    else
    {
      SendDataLength += PROTOCOL_FIXED_BIT_LENGTH;
    }

    pMessageOut[SendDataLength] = ProtocolSumCrcCheck(pMessageOut, SendDataLength);
    SendDataLength += PROTOCOL_CHECK_CODE_BIT_LENGTH;

    if (pMessageSizeOut != NULL)
    {
      *pMessageSizeOut = SendDataLength;
    }

    return true;
  }

  return false;
}
